springmvc整合shiro权限控制

一、什么是Shiro  
Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能: 
  • 认证 - 用户身份识别,常被称为用户“登录”;
  • 授权 - 访问控制;
  • 密码加密 - 保护或隐藏数据防止被偷窥;
  • 会话管理 - 每用户相关的时间敏感的状态。

对于任何一个应用程序,Shiro都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro要简单的多。


二:springmvc整合shiro

    1,在web.xml中加入如下配置

   

<!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 -->  
<!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> -->  
<!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 -->  
<!-- 通常会将此filter-mapping放置到最前面(即其他filter-mapping前面),以保证它是过滤器链中第一个起作用的 -->  
  <!-- targetFilterLifecycle值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->   

    

[html]  view plain  copy
  1. <!-- shiro start安全过滤器 -->  
  2.     <filter>  
  3.         <filter-name>shiroFilter</filter-name>  
  4.         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  5.         <async-supported>true</async-supported>  
  6.         <init-param>  
  7.             <param-name>targetFilterLifecycle</param-name>  
  8.             <param-value>true</param-value>  
  9.         </init-param>  
  10.     </filter>  
  11.   
  12.     <filter-mapping>  
  13.         <filter-name>shiroFilter</filter-name>  
  14.         <url-pattern>/*</url-pattern>  
  15.         <dispatcher>REQUEST</dispatcher>  
  16.     </filter-mapping>  
  17.     <!-- shiro end -->  

2,配置applicationContext.xml

 

<!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->  
<!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->  


[html]  view plain  copy
  1. <!-- 缓存管理器 -->  
  2.     <bean id="cacheManager" class="com.www.admin.spring.SpringCacheManagerWrapper">  
  3.         <property name="cacheManager" ref="springCacheManager"/>  
  4.     </bean>  
  5.   
  6.     <!-- 凭证匹配器 -->  
  7.     <bean id="credentialsMatcher" class="com.www.admin.user.credentials.RetryLimitHashedCredentialsMatcher">  
  8.         <constructor-arg ref="cacheManager"/>  
  9.         <property name="hashAlgorithmName" value="md5"/>  
  10.         <property name="hashIterations" value="2"/>  
  11.         <property name="storedCredentialsHexEncoded" value="true"/>  
  12.     </bean>  
  13.   
  14.     <!-- Realm实现 -->  
  15.     <bean id="userRealm" class="com.www.admin.user.realm.UserRealm">  
  16.         <property name="credentialsMatcher" ref="credentialsMatcher"/>  
  17.         <property name="cachingEnabled" value="true"/>  
  18.         <property name="authenticationCachingEnabled" value="true"/>  
  19.         <property name="authenticationCacheName" value="authenticationCache"/>  
  20.         <property name="authorizationCachingEnabled" value="true"/>  
  21.         <property name="authorizationCacheName" value="authorizationCache"/>  
  22.     </bean>  
  23.   
  24.     <!-- 会话ID生成器 -->  
  25.     <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>  
  26.   
  27.     <!-- 会话Cookie模板 -->  
  28.     <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
  29.         <constructor-arg value="sid"/>  
  30.         <property name="httpOnly" value="true"/>  
  31.         <property name="maxAge" value="-1"/>  
  32.     </bean>  
  33.   
  34.     <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
  35.         <constructor-arg value="rememberMe"/>  
  36.         <property name="httpOnly" value="true"/>  
  37.         <property name="maxAge" value="2592000"/><!-- 30天 -->  
  38.     </bean>  
  39.   
  40.     <!-- rememberMe管理器 -->  
  41.     <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">  
  42.         <!-- rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)-->  
  43.         <property name="cipherKey"  
  44.                   value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>  
  45.         <property name="cookie" ref="rememberMeCookie"/>  
  46.     </bean>  
  47.   
  48.     <!-- 会话DAO -->  
  49.     <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">  
  50.         <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>  
  51.         <property name="sessionIdGenerator" ref="sessionIdGenerator"/>  
  52.     </bean>  
  53.   
  54.     <!-- 会话验证调度器 -->  
  55.     <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">  
  56.         <property name="sessionValidationInterval" value="1800000"/>  
  57.         <property name="sessionManager" ref="sessionManager"/>  
  58.     </bean>  
  59.   
  60.     <!-- 会话管理器 -->  
  61.     <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
  62.         <property name="globalSessionTimeout" value="1800000"/>  
  63.         <property name="deleteInvalidSessions" value="true"/>  
  64.         <property name="sessionValidationSchedulerEnabled" value="true"/>  
  65.         <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>  
  66.         <property name="sessionDAO" ref="sessionDAO"/>  
  67.         <property name="sessionIdCookieEnabled" value="true"/>  
  68.         <property name="sessionIdCookie" ref="sessionIdCookie"/>  
  69.     </bean>  
  70.   
  71.     <!-- 安全管理器 -->  
  72.     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  73.         <property name="realm" ref="userRealm"/>  
  74.         <property name="sessionManager" ref="sessionManager"/>  
  75.         <property name="cacheManager" ref="cacheManager"/>  
  76.         <property name="rememberMeManager" ref="rememberMeManager"/>  
  77.     </bean>  
  78.   
  79.     <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->  
  80.     <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  81.         <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>  
  82.         <property name="arguments" ref="securityManager"/>  
  83.     </bean>  
  84.   
  85.     <!-- 基于Form表单的身份验证过滤器  -->  
  86.     <bean id="loginFormAuthenticationFilter" class="com.www.admin.filter.shiro.LoginFormAuthenticationFilter"/>  
  87.   
  88.     <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">   
  89.         <property name="redirectUrl" value="/admin/login.do" />   
  90.     </bean>   
  91.     <bean id="sysUserFilter" class="com.www.admin.filter.shiro.SysUserFilter"/>  
  92.   
  93.     <!-- Shiro的Web过滤器 -->  
  94.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  95.         <property name="securityManager" ref="securityManager"/>  
  96.         <property name="loginUrl" value="/admin/login.do"/>  
  97.         <property name="successUrl" value="/admin/index.do"/>  
  98.         <property name="filters">  
  99.             <util:map>  
  100.                 <entry key="authc" value-ref="loginFormAuthenticationFilter"/>  
  101.                 <entry key="sysUser" value-ref="sysUserFilter"/>  
  102.                 <entry key="logout" value-ref="logoutFilter"/>  
  103.             </util:map>  
  104.         </property>  
  105.         <property name="filterChainDefinitions">  
  106.             <value>                 
  107.                 /**/*.js=anon  
  108.                 /**/*.img=anon  
  109.                 /**/*.css=anon  
  110.                 /**/*.png=anon  
  111.                 /**/*.gif=anon  
  112.                 /**/*.jpg=anon  
  113.                 /static/**=anon  
  114.                 /admin/logout.do = logout  
  115.                 /admin/login.do = authc  
  116.                 /authenticated = authc  
  117.                 /** = authc,user,sysUser           
  118.             </value>  
  119.         </property>  
  120.     </bean>  
  121.   
  122.     <!-- Shiro生命周期处理器-->  
  123.     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  

       

securityManager:这个属性是必须的。

loginUrl:没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp页面。

successUrl:登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。

unauthorizedUrl:没有权限默认跳转的页面。

3, 自定义的Realm类

    

     

[java]  view plain  copy
  1. import java.util.HashSet;  
  2. import java.util.Set;  
  3.   
  4. import javax.annotation.Resource;  
  5.   
  6. import org.apache.shiro.authc.AuthenticationException;  
  7. import org.apache.shiro.authc.AuthenticationInfo;  
  8. import org.apache.shiro.authc.AuthenticationToken;  
  9. import org.apache.shiro.authc.LockedAccountException;  
  10. import org.apache.shiro.authc.SimpleAuthenticationInfo;  
  11. import org.apache.shiro.authc.UnknownAccountException;  
  12. import org.apache.shiro.authz.AuthorizationInfo;  
  13. import org.apache.shiro.authz.SimpleAuthorizationInfo;  
  14. import org.apache.shiro.realm.AuthorizingRealm;  
  15. import org.apache.shiro.subject.PrincipalCollection;  
  16. import org.apache.shiro.util.ByteSource;  
  17.   
  18.   
  19. public class UserRealm extends AuthorizingRealm {  
  20.   
  21.     @Resource  
  22.     private UserService userService;  
  23.           
  24.         //这是授权方法    
  25.     @Override  
  26.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
  27.         String username = (String)principals.getPrimaryPrincipal();  
  28.         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();  
  29.         Set<String> permissionsSet = null;  
  30.         Set<String> permissionsSetStr = new HashSet<String>();  
  31.         try {  
  32.               
  33.             authorizationInfo.setRoles(userService.findRoles(username));  
  34.             permissionsSet = userService.findPermissions(username);  
  35.             for(String perStr:permissionsSet) {  
  36.                 if(perStr.indexOf("*")<0) {  
  37.                     permissionsSetStr.add(perStr);  
  38.                 }  
  39.             }  
  40.             authorizationInfo.setStringPermissions(permissionsSetStr);  
  41.         } catch (Exception e) {  
  42.             e.printStackTrace();  
  43.         }  
  44.         return authorizationInfo;  
  45.     }  
  46.   
  47.     //这是认证方法   
  48.     @Override  
  49.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {  
  50.   
  51.         String username = (String)token.getPrincipal();  
  52.         UserVo userVo = null;  
  53.         SimpleAuthenticationInfo authenticationInfo = null;  
  54.         try {  
  55.             userVo = userService.findByUsername(username);  
  56.             if(userVo == null) {  
  57.                 throw new UnknownAccountException();//没找到帐号  
  58.             }  
  59.             if(userVo.getLocked()==0) {  
  60.                 throw new LockedAccountException(); //帐号锁定  
  61.             }  
  62.             //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配  
  63.             authenticationInfo = new SimpleAuthenticationInfo(  
  64.                     userVo.getUsername(), //用户名  
  65.                     userVo.getPassword(), //密码  
  66.                     ByteSource.Util.bytes(userVo.getCredentialsSalt()),//salt=username+salt  
  67.                     getName()  //realm name  
  68.             );  
  69.         } catch (Exception e) {  
  70.             e.printStackTrace();  
  71.         }  
  72.        
  73.         return authenticationInfo;  
  74.     }  
  75.   
  76.     @Override  
  77.     public void clearCachedAuthorizationInfo(PrincipalCollection principals) {  
  78.         super.clearCachedAuthorizationInfo(principals);  
  79.     }  
  80.   
  81.     @Override  
  82.     public void clearCachedAuthenticationInfo(PrincipalCollection principals) {  
  83.         super.clearCachedAuthenticationInfo(principals);  
  84.     }  
  85.   
  86.     @Override  
  87.     public void clearCache(PrincipalCollection principals) {  
  88.         super.clearCache(principals);  
  89.     }  
  90.   
  91.     public void clearAllCachedAuthorizationInfo() {  
  92.         getAuthorizationCache().clear();  
  93.     }  
  94.   
  95.     public void clearAllCachedAuthenticationInfo() {  
  96.         getAuthenticationCache().clear();  
  97.     }  
  98.   
  99.     public void clearAllCache() {  
  100.         clearAllCachedAuthenticationInfo();  
  101.         clearAllCachedAuthorizationInfo();  
  102.     }  
  103.   
  104. }  

4,controller层实例   

@RequiresPermissions

例如: @RequiresPermissions({"file:read", "write:aFile.txt"} )
  
void someMethod();

要求subject中必须同时含有file:readwrite:aFile.txt的权限才能执行方法someMethod()。否则抛出异常AuthorizationException

  

[java]  view plain  copy
  1. @RequiresPermissions("sys:user:add")//此处就是控制权限的注解  
  2. @RequestMapping(value = "/add", method = RequestMethod.POST)  
  3. public ModelAndView addUser(){  
  4.     ModelAndView mav = new ModelAndView("user/add");  
  5.     List<RoleVo> roleList = userService.add();  
  6.     mav.addObject("roleList", roleList);  
  7.     return mav;  
  8. }  

5,jsp处控制

  <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>//引入标签


[javascript]  view plain  copy
  1. <div class="progess_btn" style=" text-align: left;margin-left: 120px;margin-top: -50px;">  
  2.              <shiro:hasPermission name="sys:user:add">  
  3.                  <a class="btn_sure" href="javascript:void(0);"  style=" margin-right: 58px; width: 100px;" onclick="addSubmit()">添加</a>  
  4.              </shiro:hasPermission>                 
  5.                 <a class="btn_sure" href="javascript:history.back(-1);"  style=" margin-right: 58px; width: 100px;">返回</a>  
  6.  </div>  

6.

默认,添加或删除用户的角色 或资源 ,系统不需要重启,但是需要用户重新登录。

即用户的授权是首次登录后第一次访问需要权限页面时进行加载。

但是需要进行控制的权限资源,是在启动时就进行加载,如果要新增一个权限资源需要重启系统。

7.

Springsecurity apache shiro差别:

a) shiro 配置更加容易理解,容易上手; security 配置相对比较难懂。
b) spring 的环境下, security 整合性更好。 Shiro 对很多其他的框架兼容性更好,号称是无缝集成。
c) shiro 不仅仅可以使用在 web 中,它可以工作在任何应用环境中。
d) 在集群会话时 Shiro 最重要的一个好处或许就是它的会话是独立于容器的。
e) Shiro 提供的密码加密使用起来非常方便。

8.

控制精度:

注解方式控制权限只能是在方法上控制,无法控制类级别访问。

过滤器方式控制是根据访问的URL进行控制。允许使用*匹配URL,所以可以进行粗粒度,也可以进行细粒度控制。

猜你喜欢

转载自blog.csdn.net/qq_37334435/article/details/80703955