前言:本人是刚学习java后端不久,所以通过记录一下平时所学知识,方便日后的复习,如果有出错的地方,还望包含。
1、shiro是springboot集成的一个安全框架,使用非常简单,相对于ssm来说,对初学者想要尽快入手,提供了可能。
前端的登录界面,可以用自己的,只要做好和后端接口的连接就行。
想要使用shiro,首先要引入shiro的pom坐标
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<!--配置shiro和thymeleaf,从而使不同人看到不同的页面,管理不同的权限–>-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
2、controller层对登录接口的管理
//可以同时输入两个路径,这两个路径都是指定了登录界面,需要用一个大括号括起来
//这个时候我们执行登录这个方法,一定会进行到userRealm中进行登录的认证。
@RequestMapping({"/login"})
public String login(Model model,
String userName,
String userPassword, HttpSession session)
{
System.out.println("loginController执行了。");
//1.获取Subject
Subject subject = SecurityUtils.getSubject();
//2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(userName,userPassword);
//3.执行登录方法
try {
subject.login(token);
// System.out.println(token.getUsername());
//登录成功以后,将值存放在session中,在前端通过 [[${session.username}]] 进行调用显示。
session.setAttribute("username",token.getUsername());
model.addAttribute("name",userName);
//登录成功
//跳转到test.html
return "redirect:/index";
} catch (UnknownAccountException e) {
//e.printStackTrace();
//登录失败:用户名不存在
model.addAttribute("msg", "用户名不存在");
model.addAttribute("name",userName);
return "login"; //返回登录页面
}catch (IncorrectCredentialsException e) {
//登录失败:密码错误
model.addAttribute("msg", "密码错误");
return "login"; //返回登录页面
}
}
注释,这个是后端的登录接口,当用户提交的时候,会被shiro拦截,对用户的身份进行认证,对角色的权限,进行审核。
3、在自己的包下,创建一个config的配置包,包中有两个类
第一个userRealm类
package com.newbie.demo0502.config;//package com.newbie.demo0502.config;
import com.newbie.demo0502.entity.User;
import com.newbie.demo0502.service.impl.UserServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 自定义Realm
* @author lenovo
*
*/
public class UserRealm extends AuthorizingRealm{
@Autowired
private UserServiceImpl userSerivce;
/**
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
System.out.println("执行授权逻辑");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//可以在这个从数据库中查找用户的授权信息,放入其中,就可以对不同用户的权限分配进行管理
//添加资源的授权字符串
//到数据库查询当前登录用户的授权字符串
//获取当前登录用户
Subject subject = SecurityUtils.getSubject();
//通过这句话,获取当前的用户
User user = (User)subject.getPrincipal();
//通过登录的用户名,获取当前用户的的所有信息
User dbUser=userSerivce.seleceUserByName(user.getUserName());
// //通过这句话获取用户的权限信息getPerms
info.addStringPermission(dbUser.getUserMessage());
return info;
}
/**
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
System.out.println("执行认证逻辑");
//编写shiro判断逻辑,判断用户名和密码
//1.判断用户名
UsernamePasswordToken token = (UsernamePasswordToken)auth;
//通过用户名,获取当前用户所有的信息
User user = userSerivce.seleceUserByName(token.getUsername());
if(user==null){
//用户名不存在
return null;//shiro底层会抛出UnKnowAccountException
}
//2.判断密码
return new SimpleAuthenticationInfo(user,user.getUserPassword(),"");
}
}
注释:这个是userRealm类,用户的登录的认证,和用户访问一些功能时候的授权,都是经过这里,用户的每次操作都会到这里进行权限上的判断,判断用户的角色是否有对应操作的权限。
如果想要移植到其他的项目中,需要对上面的代码进行一定的修改。
ShiroConfig
package com.newbie.demo0502.config;//package com.newbie.demo0502.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* Shiro的配置类
* @author lenovo
*
*/
@Configuration
public class ShiroConfig {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加Shiro内置过滤器
/**
* Shiro内置过滤器,可以实现权限相关的拦截器
* 常用的过滤器:
* anon: 无需认证(登录)可以访问
* authc: 必须认证才可以访问
* user: 如果使用rememberMe的功能可以直接访问
* perms: 该资源必须得到资源权限才可以访问
* role: 该资源必须得到角色权限才可以访问
*/
Map<String,String> filterMap = new IdentityHashMap<>();
//对静态资源进行放行
filterMap.put("/images/**","anon");
//设置不需要进行认证的
filterMap.put("/login", "anon"); //登录页
filterMap.put("/login1", "anon"); //登录页
// filterMap.put("/index", "anon"); //后台首页
filterMap.put("/signIn","anon"); //注册
filterMap.put("/register","anon"); //注册
filterMap.put("/welcome","anon"); //welcome页
filterMap.put("/ajaxCheckUsername","anon"); //ajax判断方法,检验用户名和密码是否存在
//注销就是一句话,太神奇了
filterMap.put("/logout","logout");
//user下全部进行拦截
filterMap.put("/*","auth");
filterMap.put("/seleceUserByName","authc");
//授权过滤器
//注意:当前授权拦截后,shiro会自动跳转到未授权页面
//设置用户接口授权
filterMap.put("/deleteUser", "perms[svip]");//需要有VIp授权的用户,才可以进入,
filterMap.put("/updateUser", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/insertUser", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/findAllUser", "perms[svip]");//这对权限的设置在userRealm中。
//设置学生接口授权
filterMap.put("/findAllStudent", "perms[普通用户]");//这对权限的设置在userRealm中。
filterMap.put("/findAllStudent", "perms[vip]");//这对权限的设置在userRealm中。
filterMap.put("/findAllStudent", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/insertStudent", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/insertStudent", "perms[vip]");//这对权限的设置在userRealm中。
filterMap.put("/updateStudent", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/deleteStudent", "perms[svip]");//这对权限的设置在userRealm中。
//设置老师接口授权
filterMap.put("/findAllTeacher", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/findAllTeacher", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/insertTeacher", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/updateTeacher", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/deleteTeacher", "perms[svip]");//这对权限的设置在userRealm中。
//设置班级接口授权
filterMap.put("/findAllClass", "perms[vip]");//这对权限的设置在userRealm中。
filterMap.put("/findAllClass", "perms[普通用户]");//这对权限的设置在userRealm中。
filterMap.put("/findAllClass", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/insertClass", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/insertClass", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/updateClass", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/seleceUserByName", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/seleceUserByName", "perms[vip]");//这对权限的设置在userRealm中。
filterMap.put("/insertStudent", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/seleceUserByName", "perms[vip]");//这对权限的设置在userRealm中。
filterMap.put("/seleceUserByName", "perms[普通用户]");//这对权限的设置在userRealm中。
filterMap.put("/seleceUserByName", "perms[svip]");//这对权限的设置在userRealm中。
filterMap.put("/*","authc"); //通用的配置在最后,省得之前的不匹配了。
//修改调整的登录页面
shiroFilterFactoryBean.setLoginUrl("/login1");
//设置未授权提示页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 创建Realm
*/
@Bean(name="userRealm")
public UserRealm getRealm(){
return new UserRealm();
}
/**
* 配置ShiroDialect,用于thymeleaf和shiro标签配合使用,可以实现未授权功能隐藏
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
注释:这个类主要是对数据表的角色,进行一系列的授权,给不同的用户绑定不同的身份,再通过shiro的方言(可以自己查一下),可以实现前端基于不同登录者的身份,显示不同的前端页面。
因为这个权限授予的底层是IdentityHashMap集合,所以很多的授权,都是根据键值对进行匹配的。
感受:使用了框架以后,只需要这两个类,就可以实现不同用户,可以看到不同的前端(这个是使用了shiro方言的功能,需要导入shiro方言的坐标,加上前端使用一个简单的权限判定的标签),才可以实现前端,根据不同的权限进行前端页面的不同显示,总之非常的方便。