Shiro请求授权
-
主要流程
-
ShiroConfig中的getShiroFilterFactoryBean,给请求设置权限,给入setFilterChainDefinitionMap中,就设定好了授权规则
- 未授权的请求跳到自己制作的非授权提示界面
-
当用户每次访问设定的请求页面就会进入UserRealm的doGetAuthorizationInfo方法中查看是否有授权
- 创建subject获取当前用户,读取用户的权限
-
先给数据库用户表加权限存放权限的列
-
-
没有权限的应该设置为其他字符,比如null,无法识别,就可以跳入未授权页面而不是500错误页面
-
ShiroConfig
-
@Configuration public class ShiroConfig { /*ShiroFilterFactoryBean*/ @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean =new ShiroFilterFactoryBean(); /*设置安全管理器*/ bean.setSecurityManager(defaultWebSecurityManager); /*添加shiro的内置过滤器 * anon 无需认证就能访问 * authc 必须认证了才能访问 * user 必须拥有记住我才能访问 * perms 拥有对某个资源的权限才能访问 * role 拥有某个角色权限才能访问 * */ /* filterMap.put("/user/add","anon"); filterMap.put("/user/update","authc");*/ Map<String, String> filterMap = new LinkedHashMap<>(); /*访问/user/add,需要user:add权限*/ filterMap.put("/user/add","perms[user:add]"); filterMap.put("/user/update","perms[user:update]"); /*可以使用通配符*/ filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); /*设置登录请求*/ bean.setLoginUrl("/tologin"); /*未授权请求*/ bean.setUnauthorizedUrl("/noauth"); return bean; } /*DefaultWebSecurityManager*/ @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); /*关联realm*/ securityManager.setRealm(userRealm); return securityManager; } /*创建Realm对象,需要自定义类*/ @Bean public UserRealm userRealm(){ return new UserRealm(); } }
-
-
-
制作一个非授权界面
-
UserRealm
-
/*继承授权*/ public class UserRealm extends AuthorizingRealm { @Autowired UserServiceImpl userService; /*授权*/ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了授权Authorization"); /*这种方式叫硬编码,正常应该放在数据库中*/ SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //info.addStringPermission("user:add"); /*要将info对象返回回去*/ /*拿到当前登录的这个对象, 拿到User*/ Subject subject = SecurityUtils.getSubject(); User principal = (User) subject.getPrincipal(); info.addStringPermission(principal.getPerms()); System.out.println(principal.getPerms()); return info; } /*认证*/ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了认证Authentication"); /*用户名和密码在数据库中获取*/ UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; User user = userService.selectUserByName(userToken.getUsername()); if (user==null) { /*会抛出异常,UnknownAccountException */ return null; } return new SimpleAuthenticationInfo(user,user.getPwd(),""); } }
-
-
通过这条语句的,第一个参数principal,将user传递到检查授权方法中
-
每一次请求,会进行doGetAuthorizationInfo ,subject代表当前用户,获取当前用户的权限,对比是否和当前请求规定的权限一致
-
一致就通过,不一致就跳转到非授权提示界面
-
-
-
用户update
-
还比较浅显,如果一个用户多个授权应该如何实现,
-
-
这里有个带s的,应该用于一个用户多个授权
-
-
就是这么实现,如果要改造数据库的话,感觉应该做个授权的pojo和表,能让一个用户多个授权,或者字符串拼接拆分吧