一、回顾
回顾上文我们了解到Shiro的认证
1.准备好 login 接口
2.在自定义的 Realm 中,重写 doGetAuthenticationInfo 方法进行校验
二、授权
所谓授权,可以理解是 “身份辨别”
1.准备一个“未授权”接口,用来 给没有权限的用户进行跳转(避免他尴尬哈哈哈)
@GetMapping("/unauth")
@ResponseBody
public String unauthorized(){
return "您未被赋予权限!";
}
2.在 ShiroConfig 中进行配置,设置 接口权限 以及 跳转目标
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.LinkedHashMap;
import java.util.Map;
/**
* @author LiuXT
*/
@Configuration
public class ShiroConfig {
//3 ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("SecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// 设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加 Shiro内置过滤器
/*
* anon: 无需认证即可访问
* authc: 需要认证才能访问
* user: 需要拥有 ‘记住我’ 才能用
* perms: 拥有对某个资源权限才能访问
* role: 拥有某个角色权限才能访问
*/
Map<String,String> map = new LinkedHashMap<>();
//拦截器 ("请求路径",“请求过滤方式 ”)
//map.put("/testshiro/aaa","authc");
//map.put("/testshiro/bbb","authc");
//map.put("/testshiro/*","authc");
//表示:用户的权限 不是 admin 则没有权限访问 /testshiro/aaa
map.put("/testshiro/aaa","roles[admin]");
//配置 如果被拦截 则跳转到 XXX请求
bean.setLoginUrl("/testshiro/tologin");
//配置 如果未授权 则跳转到 XXX请求
bean.setUnauthorizedUrl("/testshiro/unauth");
bean.setFilterChainDefinitionMap(map);
return bean;
}
//2 DefaultWebSecurityManager
@Bean(name = "SecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("liuRealm") LiuRealm liuRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 关联 LiuRealm
securityManager.setRealm(liuRealm);
return securityManager;
}
//1 创建 realm对象,自定义 Realm
@Bean
public LiuRealm liuRealm(){
return new LiuRealm();
}
}
3.自定义 Realm 中的授权部分进行变更,实现权限校验
import com.liu.entity.UserMpdemo;
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;
/**
* @author LiuXT
*/
public class LiuRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了 -> 授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
UserMpdemo user = (UserMpdemo) subject.getPrincipal();
System.out.println(user.getUsername() + " 的权限是 " + user.getRoles());
// 给 info 添加授权信息 相当于告诉shiro,爷的权限就是这个!你知道了吧!?
info.addRole(user.getRoles());
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行 -> 认证");
// 1 模拟数据 (实际需要根据token从库中查询出来)
UserMpdemo user = new UserMpdemo("001", "root", "123123", "admin");
// 2 将token转为 可以提取内容的 userToken
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
if (!userToken.getUsername().equals(user.getUsername())) {
// 返回null 即抛出异常 UnknownAccountException -> 用户不存在
return null;
}
// 密码校验 完成后 所有校验即完成
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), "");
return info;
}
}
效果:
因为咱们 认证 时使用的是模拟数据,所以进行对模拟数据更改属性 roles 来进行检测
1.当 ShiroConfig 中设置权限为 admin,且咱们数据的权限也是 admin 时,先登录再访问 aaa没问题~ 完美~
2.当 ShiroCofig 中设置权限为 admin,但模拟数据的权限为 admin123 时,先登录再访问 aaa时权限校验不通过~ 完美~