Shiro通过注解配置授权
Posted xk920
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro通过注解配置授权相关的知识,希望对你有一定的参考价值。
接着上一篇文章的基础之上:
pom中添加一个切面编程aop的依赖:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency>
然后在spring-mvc.xml文件中开启aop并做相关配置:
<!--//开启aop--> <aop:config proxy-target-class="true"/> <!--创建一个保证shiro内部Lifecycle正常执行的对象--> <bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!--创建一个shiro授权生效的对象--> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean>
接着在controller中添加:
@RequiresRoles("admin")//这个注解的含义是:必须具备指定角色才可以访问这个链接,执行这个方法 @RequestMapping(value = "/testRole",method = RequestMethod.GET) @ResponseBody public String testRole(){ return "test Role success"; } @RequiresRoles("admin1")//这个注解的含义是:必须具备指定角色才可以访问这个链接,执行这个方法 @RequestMapping(value = "/testRole1",method = RequestMethod.GET) @ResponseBody public String testRole1(){ return "test Role success";
然后运行:
先登录:
登录成功后访问url:
访问成功,说明具备角色。
接着访问另一个url:/testRole1
报错500,
Subject does not have role [admin1]
说明controller中的注解已经生效。
还有另一种注解:指定具有相应权限才可访问
@RequiresPermissions({"login","user:select"})//这个注解的含义是:必须具备指定权限才可以访问这个链接,执行这个方法 @RequestMapping(value = "/testPermission",method = RequestMethod.GET) @ResponseBody public String testPermission(){ return "test Permission success"; }
这里在上一篇博客的基础之上,还需要修改一下自定义Realm中的授权内容与getPermissionsByUserName方法,修改后的内容如下:
@Component public class CustomRealm extends AuthorizingRealm { @Autowired private UserDao userDao; //授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //1.通过主体传过来的认证信息中去获取用户名 String userName = (String) principalCollection.getPrimaryPrincipal(); //实际开发时这里从数据库或者缓存中获取角色数据 Set<String> roles = getRolesByUserName(userName); Set<String> permissions = getPermissionsByUserName(userName); //将取来的角色数据与权限数据返回 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //设置权限 simpleAuthorizationInfo.setStringPermissions(permissions); //设置角色 simpleAuthorizationInfo.setRoles(roles); return simpleAuthorizationInfo; } /** * 根据用户名获取权限信息 * @return */ private Set<String> getPermissionsByUserName(String userName) { List<String> list = userDao.queryPermissionsByUserName(userName); Set<String> sets= new HashSet<>(list); return sets; } /** * 根据账号取角色信息 * @param userName * @return */ private Set<String> getRolesByUserName(String userName) { List<String> list = userDao.queryRolesByUserName(userName); Set<String> sets = new HashSet<>(list); return sets; } //认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1.通过主体传过来的认证信息中去获取用户名 String userName = (String)authenticationToken.getPrincipal(); //2.通过用户名到数据库中获取凭证 String password = getPasswordByUserName(userName); if (password == null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo (userName,password,"customRealm"); return authenticationInfo; } /** * 模拟数据库查询凭证 * @param userName * @return */ private String getPasswordByUserName(String userName){ //查询数据库 user user = userDao.getUserByUserName(userName); if (user != null){ return user.getPassword(); } return null; } public static void main(String[] args){ //因为是模拟数据库操作, //数据库中的密码应该都是被MD5加密过的数据 //所以需要在这里直接打印出加密后的密码 Md5Hash md5Hash = new Md5Hash("123qwe"); System.out.println(md5Hash.toString()); } }
这里在userDao中插入了queryPermissionsByUserName(userName);方法,代码如下:
@Override public List<String> queryPermissionsByUserName(String userName) { String sql = "select r.permission from roles_permissions r,user_roles u where u.role_name = r.role_name and u.username = ?"; List<String> permissions = jdbcTemplate.query(sql, new String[]{userName}, new RowMapper<String>() { @Override public String mapRow(ResultSet resultSet, int i) throws SQLException { return resultSet.getString("permission"); } }); if (CollectionUtils.isEmpty(permissions)){ return null; }else { for (String s : permissions) { System.out.println(s); } return permissions; } }
运行访问结果如下:
PS:这里一定要注意数据的设置与返回,也就自定义Realm中的:
//实际开发时这里从数据库或者缓存中获取角色数据 Set<String> roles = getRolesByUserName(userName); Set<String> permissions = getPermissionsByUserName(userName); //将取来的角色数据与权限数据返回 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //设置权限 simpleAuthorizationInfo.setStringPermissions(permissions); //设置角色 simpleAuthorizationInfo.setRoles(roles); return simpleAuthorizationInfo;
这部分代码,之前因为马虎,
//设置权限 simpleAuthorizationInfo.setStringPermissions(permissions);
忘记塞这个步骤中的permissions了,导致疯狂500错误:org.apache.shiro.authz.UnauthorizedException: Subject does not have permission
以上是关于Shiro通过注解配置授权的主要内容,如果未能解决你的问题,请参考以下文章