使用Shiro 集合Spring来实现权限控制
Posted ReiNer_Shir2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Shiro 集合Spring来实现权限控制相关的知识,希望对你有一定的参考价值。
这只是笔记
web.xml中引入 spring-shiro.xml
spring-shiro.xml :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <description>Shiro 配置</description> <!-- 权限配置对照表 * @see /admin=authc,roles[admin] 表示用户必需已通过认证,并拥有admin角色才可以正常发起'/admin'请求 数据库权限格式admin:list * @see /edit=authc,perms[admin:edit] 表示用户必需已通过认证,并拥有admin:edit权限才可以正常发起'/edit'请求 * @see /home=user 表示用户不一定需要已经通过认证,只需要曾经被Shiro记住过登录状态就可以正常发起'/home'请求 * @see /admins/**=anon 无参,表示可匿名使用,可以理解为匿名用户或游客 * @see /admins/user/**=authc 无参,表示需认证才能使用 * @see /admins/user/**=authcBasic 无参,表示httpBasic认证 * @see /admins/user/**=user 无参,表示必须存在用户,当登入操作时不做检查 * @see /admins/user/**=ssl 无参,表示安全的URL请求,协议为https * @see /admins/user/**=perms[user:add:*] * @see 参数可写多个,多参时必须加上引号,且参数之间用逗号分割,如/admins/user/**=perms["user:add:*,user:modify:*"] * @see 当有多个参数时必须每个参数都通过才算通过,相当于isPermitedAll()方法 * @see /admins/user/**=port[8081] * @see 当请求的URL端口不是8081时,跳转到schemal://serverName:8081?queryString * @see 其中schmal是协议http或https等,serverName是你访问的Host,8081是Port端口,queryString是你访问的URL里的?后面的参数 * @see /admins/user/**=rest[user] * @see 根据请求的方法,相当于/admins/user/**=perms[user:method],其中method为post,get,delete等 * @see /admins/user/**=roles[admin] 参数可写多个,多个时必须加上引号,且参数之间用逗号分割,如/admins/user/**=roles["admin,guest"] * @see 当有多个参数时必须每个参数都通过才算通过,相当于hasAllRoles()方法 --> <!-- 权限配置 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/direct.html" /> <property name="successUrl" value="/index.html" /> <property name="unauthorizedUrl" value="/403.html" /> <!-- 无权限跳转页面 --> <property name="filters"> <util:map> <entry key="authc"> <bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter"/> <!-- <bean class="com.hbs.dipper.interceptor.MethodAuthenticationFilter"/> --> </entry> </util:map> </property> <property name="filterChainDefinitions"> <value> <!-- 静态文件控制 --> /css/** = anon /images/** = anon /js/** = anon /index.html = user /direct.html = anon /403.html = anon /login.html = anon <!-- 用户管理权限 --> /user/logout = anon <!-- 无需控制 --> /user/getCurrentUser = user <!-- 登陆即不做检查 --> /user/updatePwd = user /user/login/** = anon /user/get*/** = perms[user:view] <!-- 查看权限 --> /view/user/** = perms[user:view] <!-- html权限控制 --> /user/add*/** = perms[user:add] <!-- 添加权限 --> /user/delete*/** = perms[user:delete] <!-- 删除权限 --> /user/update*/** = perms[user:update] <!-- 修改权限 --> /user/changeStatus/** = perms[user:enableOrDisable] <!-- 启用禁用用户 --> /user/resetPassword/** = perms[user:resetPwd] <!-- 重制密码 --> <!-- 部门权限 --> /company/get*/** = perms[company:view] <!-- 查看权限 --> /view/company/** = perms[company:view] <!-- html权限控制 --> /company/add*/** = perms[company:add] <!-- 添加权限 --> /company/delete*/** = perms[company:delete] <!-- 删除权限 --> /company/update*/** = perms[company:update] <!-- 修改权限 --> <!-- 角色权限 --> /role/get*/** = perms[role:view] <!-- 查看权限 --> /view/role/** = perms[role:view] <!-- html权限控制 --> /role/add*/** = perms[role:add] <!-- 添加权限 --> /role/delete*/** = perms[role:delete] <!-- 删除权限 --> /role/update*/** = perms[role:update] <!-- 修改权限 --> <!-- 权限管理 --> /permission/get*/** = perms[permission:view] <!-- 查看权限 --> /view/permission/** = perms[permission:view] <!-- html权限控制 --> /permission/add*/** = perms[permission:add] <!-- 添加权限 --> /permission/delete*/** = perms[permission:delete] <!-- 删除权限 --> /permission/update*/** = perms[permission:update] <!-- 修改权限 --> /**=rest[authc]<!-- 拦截所有get、post请求 --> </value> <!-- /**=rest[authc] 验证所有后台如get、post请求 --> </property> </bean> <bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter"> <property name="redirectUrl" value="/login" /> </bean> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="monitorRealm" /> <!-- 需要使用cache的话加上这句 <property name="cacheManager" ref="shiroEhcacheManager" /> --> </bean> <!-- depends-on 表示在实例化该对象之前先实例化 depends-on中的对象 --> <bean id="monitorRealm" class="com.hbs.dipper.interceptor.MonitorRealm" /> <!-- 启用spring注解方式拦截shiro权限 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> <!-- 自定义角色过滤器 支持多个角色可以访问同一个资源 eg:/home.jsp = authc,roleOR[admin,user] 用户有admin或者user角色 就可以访问--> <!-- <bean id="roleOR" class="com.yale.app.security.OneRoleAuthorizationFilter"/> --> <!-- srping注解配置 Post processor that automatically invokes init() and destroy() methods --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 启用shiro为spring配置的bean注释,只运行在lifecycleBeanProcessor之后 --> <bean id="annotationProxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <!-- 用户授权信息Cache, 采用EhCache,需要的话就配置上此信息 <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml" /> </bean> --> <!-- spring对ehcache的缓存工厂支持 --> <!-- <bean id="ehCacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml" /> </bean> --> </beans>
shiro加载权限具体实现类
package com.hbs.dipper.interceptor; import java.util.List; import javax.annotation.Resource; import org.apache.log4j.Logger; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Component; import com.hbs.dipper.system.model.Permission; import com.hbs.dipper.system.model.Role; import com.hbs.dipper.system.model.User; import com.hbs.dipper.system.service.PermissionService; import com.hbs.dipper.system.service.RoleService; import com.hbs.dipper.system.service.UserService; import com.hbs.dipper.util.SpringContextUtil; @Component public class MonitorRealm extends AuthorizingRealm { //由于shiro是在其他service之前加载,所以必须在运行时加载 UserService userService; RoleService roleService; PermissionService permissionService; private Logger logger = Logger.getLogger(MonitorRealm.class); /** * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用. * 将权限查出来 */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { logger.debug("get permissions================================>"); Subject currentUser =SecurityUtils.getSubject(); Session session = currentUser.getSession(); User user = (User) session.getAttribute("user"); if( user != null ) { SimpleAuthorizationInfo info = (SimpleAuthorizationInfo) session.getAttribute("info"); if(info==null){ info = new SimpleAuthorizationInfo(); if(user.getUserId().equals(1)){//超级管理员,查出所有权限 info.addRole("admin"); List<Permission> permissions = permissionService.getList(null); addPermission(info,permissions); }else{//从数据库查出权限并添加 List<Role> roles = roleService.getRoleByUser(user.getUserId()); for (Role role : roles) { info.addRole(role.getRoleName()); List<Permission> permissions = permissionService.getPermissionByRole(role.getRoleId()); for (Permission permission : permissions) { info.addStringPermission(permission.getPermissionCode()); } } } session.setAttribute("info", info);//缓存到session中 } return info; } else { throw new AuthorizationException("login user is null!"); } } /** * @Title: addPermission * @Description: TODO(迭代添加权限) * @param @param info * @param @param list 参数 * @return void 返回类型 * @throws */ public void addPermission(SimpleAuthorizationInfo info,List<Permission> list){ for (Permission permission : list) { info.addStringPermission(permission.getPermissionCode()); if(permission.getChildren()!=null&&permission.getChildren().size()>0) addPermission(info,permission.getChildren()); } } /** * 认证回调函数,登录时调用. * 经测试登陆时会调用两次。。。 */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken authcToken) throws AuthenticationException { bind(); logger.debug("login=================================>"); UsernamePasswordToken token = (UsernamePasswordToken) authcToken; String password = String.valueOf(token.getPassword()); //调用操作数据库的方法查询user信息 User user = userService.getByLoginName(token.getUsername()) ; if( user != null ) { if(password.equals(user.getPassword())){ return new SimpleAuthenticationInfo(user.getUserId(), user.getPassword(), getName()); }else{ return null; } } else { return null; } } private void bind(){ if(userService==null) userService = (UserService) SpringContextUtil.getBean("userService"); if(roleService==null) roleService = (RoleService) SpringContextUtil.getBean("roleService"); if(permissionService==null) permissionService = (PermissionService) SpringContextUtil.getBean("permissionService"); } public void clearCachedAuthorizationInfo(String principal) { SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName()); clearCachedAuthorizationInfo(principals); } }
尚未解决的问题: 无法在shiro的Realm中使用注解 ,报空异常,初步判断是在spring加载其他bean之前执行了
以上是关于使用Shiro 集合Spring来实现权限控制的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + Spring Cloud 实现权限管理系统 后端篇(二十四):权限控制(Shiro 注解)
Spring Boot + Vue + Shiro 实现前后端分离权限控制