怎么利用shiro权限动态控制每个url资源呢?主要包括jsp(html)页面、action的url访问,而静态资源和登录资源则可直接访问。
所谓动态控制url就是url的权限控制不是手动写死在配置文件中,而是根据数据库的变化而变化。
表结构:
user2:用户表
t_role:角色表
t_user_role:用户角色表
t_privilege:权限资源表
t_role_privilege:角色权限资源表
shiro动态控制url资源:
applicationContext-shiro.xml配置chainDefinitionSectionMetaSource:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <description>apache shiro配置</description> <bean id="chainDefinitionSectionMetaSource" class="com.test.www.web.filter.ChainDefinitionSectionMetaSource"> <property name="filterChainDefinitions"> <value> <!-- 静态资源允许访问 --> <!-- /** = anon --> <!-- /app/** = anon /assets/** = anon --> <!-- 登录页允许访问 --> <!-- /user/login.htm = anon --> <!-- /login.jsp = anon --> <!-- /*.jsp = anon --> <!-- /js/**=anon --> <!-- 登录页面 --> /index2.jsp = anon /js/** = anon /css/** = anon /images/** = anon /assets/** = anon /test/loginAdmin.html=anon /logout=logout <!-- 这才是对退出的配置 --> <!-- /test/add.html = perms["user:add"] --> <!-- /test/add.html = perms["/test/add.html"] --> <!-- 其他资源需要认证 --> <!-- /** = authc --> <!-- /logout=logout --> <!-- 这才是对退出的配置,不能放在/** = authc的后面 --> </value> </property> </bean> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="filters"> <map> <entry key="logout" value-ref="logoutFilter"/> </map> </property> <property name="securityManager" ref="securityManager"/> <!-- <property name="loginUrl" value="/index2.jsp"/> <property name="successUrl" value="/main/main.htm"/> <property name="unauthorizedUrl" value="/page/401.htm"/> --> <!-- shiro判断是否登录,没有登录则跳转到登录页面,loginUrl对应登录页面的路径 --> <property name="loginUrl" value="/index2.jsp"/> <property name="unauthorizedUrl" value="/page/401.htm"/><!-- /page/401.htm --> <property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" /> </bean> <!-- 缓存管理器 使用Ehcache实现 --> <!-- <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" p:cacheManagerConfigFile="/WEB-INF/conf/ehcache-shiro.xml"> </bean> --> <!-- 会话DAO --> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"/> <!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="sessionDAO" ref="sessionDAO"/> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realms"> <list> <ref bean="securityRealm"/> </list> </property> <!-- cacheManager,集合spring缓存工厂 --> <!-- <property name="cacheManager" ref="shiroEhcacheManager" /> <property name="sessionManager" ref="sessionManager" /> --> </bean> <!-- Shiro生命周期处理器 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> </beans>
ChainDefinitionSectionMetaSource.java:
package com.test.www.web.filter; import java.text.MessageFormat; import java.util.List; import javax.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.config.Ini; import org.apache.shiro.config.Ini.Section; import org.springframework.beans.factory.FactoryBean; import com.test.www.web.entity.user.TPrivilege; import com.test.www.web.service.user.TPrivilegeService; public class ChainDefinitionSectionMetaSource implements FactoryBean<Ini.Section>{ public static final String PREMISSION_STRING="perms["{0}"]"; private String filterChainDefinitions; /*private PrivilegeDao privilegeDao; public PrivilegeDao getPrivilegeDao() { return privilegeDao; }*/ @Resource private TPrivilegeService tPrivilegeService; public String getFilterChainDefinitions() { return filterChainDefinitions; } @Resource public void setFilterChainDefinitions(String filterChainDefinitions) { String fiter="";//改正后的url配置 /*List<Privilege> list = privilegeDao.getAll(); for (Iterator<Privilege> it = list.iterator(); it.hasNext();) { Privilege privilege = it.next(); if(!StringUtils.isEmpty(privilege.getUrl())) { fiter+="/"+privilege.getUrl()+" = authc," +MessageFormat.format(PREMISSION_STRING,privilege.getPerms()) +" "; }//追加beans.xml中已经有的过滤 }*/ List<TPrivilege> tPrivilegeList = tPrivilegeService.selectAllPrivileges(); if(tPrivilegeList!=null && tPrivilegeList.size()>0){ for (TPrivilege tPrivilege : tPrivilegeList) { if(!StringUtils.isEmpty(tPrivilege.getUrl())) { fiter += tPrivilege.getUrl()+" = authc," +MessageFormat.format(PREMISSION_STRING,tPrivilege.getUrl()) +" "; }//追加beans.xml中已经有的过滤 } } //对url拦截 fiter += "/**"+" = authc" +" "; //fiter+="/test/add.html"+" = authc," +MessageFormat.format(PREMISSION_STRING,"/test/add.html") +" "; //fiter+="/js/**"+" = authc," +MessageFormat.format(PREMISSION_STRING,"/js/**") +" "; //fiter+="/js/**"+" = " +MessageFormat.format(PREMISSION_STRING,"/js/**") +" "; System.out.println(filterChainDefinitions+fiter); this.filterChainDefinitions = filterChainDefinitions+fiter; } /*@Resource public void setPrivilegeDao(PrivilegeDao privilegeDao) { this.privilegeDao = privilegeDao; }*/ public Section getObject(){ Ini ini = new Ini();//网上好多都是在这里配置URL的。但是发现是错误的。 ini.load(filterChainDefinitions); Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME); return section; } public Class<?> getObjectType() { return this.getClass(); } public boolean isSingleton() { return false; } }
服务器启动的时候会执行ChainDefinitionSectionMetaSource类,加载系统权限资源表所有的url到filterChainDefinitions中(在filterChainDefinitions后追加),从而实现对所有url资源的权限控制的配置:
这个类就是用来在filterChainDefinitions中追加url资源权限控制的。
注意:
/** = authc应放在最后,否则会影响追加的权限资源的控制。
当访问资源的时候,例如/test/toAddUser.html,就会进入shiro授权方法中进行权限校验,如果没有权限则进入到401未授权,否则正常访问。
SecurityRealm.java:
package com.test.www.web.security; import java.util.List; import javax.annotation.Resource; 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.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.stereotype.Component; import com.test.www.web.entity.user.TRolePrivilegeKey; import com.test.www.web.entity.user.TUserRoleKey; import com.test.www.web.entity.user.User; import com.test.www.web.service.user.TRolePrivilegeService; import com.test.www.web.service.user.TUserRoleService; import com.test.www.web.service.user.UserService; /** * 用户身份验证,授权 Realm 组件 * **/ @Component(value = "securityRealm") public class SecurityRealm extends AuthorizingRealm { @Resource private UserService userService; @Resource private TUserRoleService tUserRoleService; @Resource private TRolePrivilegeService tRolePrivilegeService; /** * 权限检查 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { /*SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); String username = String.valueOf(principals.getPrimaryPrincipal()); System.out.println("ssssssss");*/ String username = principals.getPrimaryPrincipal().toString() ; System.out.println(username); Subject subject = SecurityUtils.getSubject(); User user = (User)subject.getPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo() ; /*Set<String> roleName = t_userService.findRoles(username) ; Set<String> permissions = t_userService.findPermissions(username) ;*/ //final List<Role> roleInfos = roleService.selectRolesByUserId(user.getUserId()); /*for (Role role : roleInfos) { // 添加角色 System.err.println(role); authorizationInfo.addRole(role.getRoleSign()); final List<Permission> permissions = permissionService.selectPermissionsByRoleId(role.getRoleId()); for (Permission permission : permissions) { // 添加权限 System.err.println(permission); authorizationInfo.addStringPermission(permission.getPermissionSign()); } }*/ List<TUserRoleKey> tUserRoleKeyList = tUserRoleService.selectRolesByUserId(user.getId()); if(tUserRoleKeyList != null && tUserRoleKeyList.size()>0){ for(TUserRoleKey tUserRoleKey : tUserRoleKeyList){ authorizationInfo.addRole(tUserRoleKey.getCode()); List<TRolePrivilegeKey> tRolePrivilegeKeyList = tRolePrivilegeService.selectPrivilegesByRoleId(tUserRoleKey.getRoleId()); for(TRolePrivilegeKey tRolePrivilegeKey : tRolePrivilegeKeyList){ authorizationInfo.addStringPermission(tRolePrivilegeKey.getUrl()); } } } //Set<String> roleName = new HashSet<String>(); //Set<String> permissions = new HashSet<String>(); //查询角色 //roleName.add("admin"); //根据角色查询权限 //permissions.add("/test/add.html1"); //pub:coursecategory user:add //permissions.add("/js/**"); //permissions.add("/jsp"); //authorizationInfo.setRoles(roleName); //authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } /** * 登录验证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /* String username = String.valueOf(token.getPrincipal()); String password = new String((char[]) token.getCredentials()); System.out.println("aaaaaaa"); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName());*/ //int i = 1/0; //获取用户账号 //验证账号密码 UsernamePasswordToken userToken = (UsernamePasswordToken) token; System.out.println("1:"+userToken.getUsername()); User user = userService.getUserByUserName(userToken.getUsername()); System.out.println("2"); if (user != null){ //将查询到的用户账号和密码存放到 authenticationInfo用于后面的权限判断。第三个参数传入realmName。 AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getSimpleName()) ; return authenticationInfo ; }else{ return null ; } } }
至此,shiro动态控制url权限资源已完成。
说明:
url资源(action、静态html或动态页面jsp的url)保存在数据库中。