Shiro使用笔记

0 本文主要涉及

shiro在基于Spring和SpringMVC的前后端分离的JavaWeb项目中认证和授权授权功能的使用

shiro简介

shiro是Apache提供的开源的基于Java实现的安全框架
官网:http://shiro.apache.org/index.html
优点:配套功能完善,接口易于使用
主要功能:身份验证,权限验证,会话管理、加密等等


基本架构:

Subject :实体,代表当前用户,方便交互,实际功能逻辑是由SecurityManager实现
SecurityManager : 安全管理器,负责所有与安全相关的操作,是Shiro的核心,负责与Shiro的其他组件进行交互
Realm : Shiro从Realm获取安全数据(如用户,角色,权限),数据源,需要我们自己实现并提供给框架
Authenticator : 负责身份验证,提供接口,需要我们自己实现并提供给框架
Authorizer :负责权限验证,提供接口,需要我们自己实现并提供给框架
SessionManager 会话管理器,不仅仅可以在Web环境中使用,也可以在普通javaSE中使用
SessionDAO:所有会话的CRUD功能
CacheManager:缓存控制器,来管理用户,角色,权限等的缓存
Cryptography : 密码模块,提供了一些常见的加密组件用于加密和解密


shiro配置集成

0 依赖配置

使用了Maven进行项目依赖管理,JavaWeb基础的依赖这里就不多说了,Shiro相关的如下
[html]  view plain  copy
  1. <dependency>  
  2.     <groupId>org.apache.shiro</groupId>  
  3.     <artifactId>shiro-core</artifactId>  
  4.     <version>1.4.0</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.apache.shiro</groupId>  
  8.     <artifactId>shiro-web</artifactId>  
  9.     <version>1.4.0</version>  
  10. </dependency>  
  11. <dependency>  
  12.     <groupId>org.apache.shiro</groupId>  
  13.     <artifactId>shiro-spring</artifactId>  
  14.     <version>1.4.0</version>  
  15. </dependency>  
  16. <dependency>  
  17.     <groupId>org.apache.shiro</groupId>  
  18.     <artifactId>shiro-ehcache</artifactId>  
  19.     <version>1.4.0</version>  
  20. </dependency>  
  21. <dependency>  
  22.     <groupId>de.svenkubiak</groupId>  
  23.     <artifactId>jBCrypt</artifactId>  
  24.     <version>0.4.1</version>  
  25. </dependency>  
  26. <dependency>  
  27.     <groupId>net.sf.ehcache</groupId>  
  28.     <artifactId>ehcache</artifactId>  
  29.     <version>2.10.2</version>  
  30. </dependency>  

1 继承实现一个Realm,实现认证和授权的接口

Shiro框架不会去维护用户、角色和权限,需要我们自己去设计/提供,然后通过相应的接口注入给Shiro使用。
具体的,首先设计用户 角色和权限的表(简单的就三个表,一个用户有一种角色,每种角色有多种权限,复杂的可以建中间表实现多对多的映射关系)
然后实现一个基本的认证和鉴权所需的DAO,大概需要根据用户名获取用户,根据用户名获取角色集合,根据用户名获取权限集合(不一定是这样的,可以根据自己Realm的实现所需提供对应的DAO方法)
继承AuthorizingRealm实现一个自己的Realm,在Realm中主要工作就是实现doGetAuthorizationInfo(认证),doGetAuthenticationInfo(鉴权)两个方法,代码如下(代码中使用了BCrypt一种更方便的加盐hash方案,还带有重复登录限制逻辑)
[java]  view plain  copy
  1. public class MyRealm extends AuthorizingRealm  
  2. {  
  3.     @Autowired  
  4.     private AuthorityService authorityService;//底层调用了上面所说的DAO  
  5.   
  6.     public MyRealm()  
  7.     {  
  8.         super();  
  9.         //BcryptPasswordMatcher  
  10.         setCredentialsMatcher(new CredentialsMatcher()  
  11.         {  
  12.             @Override  
  13.             public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)  
  14.             {  
  15.                 UsernamePasswordToken userToken = (UsernamePasswordToken) token;  
  16.                 String name = userToken.getUsername();  
  17.                 String password = new String(userToken.getPassword());  
  18.                 String hashed = info.getCredentials().toString();  
  19.   
  20.                 //重复登陆限制  
  21.                 Cache<Object, Object> passwordRetryCache = getCacheManager().getCache("passwordRetryCache");  
  22.                 Integer count = (Integer) passwordRetryCache.get(name);  
  23.                 if(count == null)  
  24.                 {  
  25.                     passwordRetryCache.put(name, 1);  
  26.                 }  
  27.                 else  
  28.                 {  
  29.                     passwordRetryCache.put(name, count++);  
  30.                     if(count > 5)  
  31.                     {  
  32.                         throw new ExcessiveAttemptsException();  
  33.                     }  
  34.                 }  
  35.   
  36.                 boolean matches = BCrypt.checkpw(password, hashed);  
  37.                 if(matches)  
  38.                 {  
  39.                     passwordRetryCache.remove(name);  
  40.                 }  
  41.                 return matches;  
  42.             }  
  43.         });  
  44.     }  
  45.   
  46.     /** 
  47.      * 用于的权限的认证。 
  48.      * 
  49.      * @param principalCollection 
  50.      * @return 
  51.      */  
  52.     @Override  
  53.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection)  
  54.     {  
  55.         String username = principalCollection.getPrimaryPrincipal().toString();  
  56.         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
  57.   
  58.         //用户角色(role)放入到Authorization里。  
  59.         Set<String> roleName = authorityService.getRoles(username);  
  60.         info.setRoles(roleName);  
  61.   
  62.         //用户权限(permission)放入到Authorization里。  
  63.         Set<String> permissions = authorityService.getPermissions(username);  
  64.         info.setStringPermissions(permissions);  
  65.   
  66.         return info;  
  67.     }  
  68.   
  69.     /** 
  70.      * 首先执行这个登录验证 
  71.      * 
  72.      * @param authenticationToken 
  73.      * @return 
  74.      * @throws AuthenticationException 
  75.      */  
  76.     @Override  
  77.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException  
  78.     {  
  79.         //UsernamePasswordToken对象用来存放提交的登录信息  
  80.         UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;  
  81.         //获取用户账号  
  82.         String username = token.getUsername();  
  83.         //查出是否有此用户  
  84.         UserEntity user = authorityService.getUserByUsername(username);  
  85.         if(user != null)  
  86.         {  
  87.             //若存在,将用户账号和密码存放到 authenticationInfo用于后面的权限判断。第三个参数传入realName。  
  88.             return new SimpleAuthenticationInfo(user.getName(), user.getPassword(), user.getRealName());  
  89.         }  
  90.         else  
  91.         {  
  92.             // 用户名不存在抛出异常  
  93.             throw new UnknownAccountException();  
  94.         }  
  95.     }  
  96. }  

2 配置缓存

缓存通过EhCache实现
在缓存的SpringBean中写入shiroEncacheManager
<!--shiro缓存管理-->
<bean id="shiroEncacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"
      p:cache-manager-ref="ehcache"/>
具体缓存申明如下
[html]  view plain  copy
  1. <ehcache>  
  2.     <!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->  
  3.     <diskStore path="java.io.tmpdir"/>  
  4.     <!--  
  5.      缓存配置  
  6.             name:缓存名称。  
  7.             maxElementsInMemory:缓存最大个数。  
  8.             eternal:对象是否永久有效,一但设置了,timeout将不起作用。  
  9.             timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。  
  10.             timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。  
  11.             overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。  
  12.             diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。  
  13.             maxElementsOnDisk:硬盘最大缓存个数。  
  14.             diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.  
  15.             diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。  
  16.             memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。  
  17.             clearOnFlush:内存数量最大时是否清除。  
  18.             maxBytesLocalHeap是用来限制缓存所能使用的堆内存的最大字节数的,其单位可以是K、M或G,不区分大小写。默认是0,表示不限制  
  19.             maxBytesLocalOffHeap是用来限制缓存所能使用的非堆内存的最大字节数,其单位也可以是K、M或G。默认是0,表示不限制。  
  20.             maxBytesLocalDisk是用来限制缓存所能使用的磁盘的最大字节数的,其单位可以是K、M或G。默认是0,表示不限制。只有在单机环境下才可以使用本地磁盘  
  21.             maxEntriesLocalHeap是用来限制当前缓存在堆内存上所能保存的最大元素数量的  
  22.      -->  
  23.     <defaultCache  
  24.             maxElementsInMemory="10000"  
  25.             eternal="false"  
  26.             timeToIdleSeconds="120"  
  27.             timeToLiveSeconds="120"  
  28.             overflowToDisk="true"/>  
  29.   
  30.     <cache name="authorizationCache"  
  31.            maxElementsInMemory="2000"  
  32.            eternal="false"  
  33.            timeToIdleSeconds="3600"  
  34.            timeToLiveSeconds="0"  
  35.            overflowToDisk="false"  
  36.            statistics="true">  
  37.     </cache>  
  38.   
  39.     <cache name="authenticationCache"  
  40.            maxElementsInMemory="2000"  
  41.            eternal="false"  
  42.            timeToIdleSeconds="3600"  
  43.            timeToLiveSeconds="0"  
  44.            overflowToDisk="false"  
  45.            statistics="true">  
  46.     </cache>  
  47.   
  48.     <cache name="shiro-activeSessionCache"  
  49.            maxElementsInMemory="2000"  
  50.            eternal="false"  
  51.            timeToIdleSeconds="3600"  
  52.            timeToLiveSeconds="0"  
  53.            overflowToDisk="false"  
  54.            statistics="true">  
  55.     </cache>  
  56.   
  57.     <!-- 登录记录缓存 锁定10分钟 -->  
  58.     <cache name="passwordRetryCache"  
  59.            maxElementsInMemory="2000"  
  60.            eternal="false"  
  61.            timeToIdleSeconds="3600"  
  62.            timeToLiveSeconds="0"  
  63.            overflowToDisk="false"  
  64.            statistics="true">  
  65.     </cache>  
  66.   
  67. </ehcache>  

3 在web.xml中配置shiro的过滤器

[html]  view plain  copy
  1. <!-- shiro过滤器定义 -->  
  2. <filter>  
  3.     <filter-name>shiroFilter</filter-name>  
  4.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  5.     <init-param>  
  6.         <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->  
  7.         <param-name>targetFilterLifecycle</param-name>  
  8.         <param-value>true</param-value>  
  9.     </init-param>  
  10. </filter>  
  11. <filter-mapping>  
  12.     <filter-name>shiroFilter</filter-name>  
  13.     <url-pattern>/*</url-pattern>  
  14. </filter-mapping>  

4 定义Shiro的SpringBean

1 配置自定义Realm

[html]  view plain  copy
  1. <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
  2. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
  3. <!-- 配置自定义Realm -->  
  4. <bean id="myRealm" class="com.cetiti.application.modules.authority.MyRealm">  
  5.     <property name="cachingEnabled" value="true"/>  
  6.     <property name="authenticationCachingEnabled" value="true"/><!-- 启用身份验证缓存,即缓存AuthenticationInfo信息,默认false -->  
  7.     <property name="authenticationCacheName" value="authenticationCache"/><!-- 缓存AuthenticationInfo信息的缓存名称 -->  
  8.   
  9.     <property name="authorizationCachingEnabled" value="true"/><!-- 启用授权缓存,即缓存AuthorizationInfo信息,默认false -->  
  10.     <property name="authorizationCacheName" value="authorizationCache"/><!-- 缓存AuthorizationInfo信息的缓存名称 -->  
  11. </bean>  

2 配置安全管理器

[html]  view plain  copy
  1. <!-- rememberMe管理器相关 -->  
  2. <!-- rememberMe Cookie模板-->  
  3. <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
  4.     <constructor-arg value="rememberMe"/><!--名称-->  
  5.     <property name="httpOnly" value="true"/>  
  6.     <property name="maxAge" value="2592000"/><!-- 30天(单位:秒) -->  
  7. </bean>  
  8. <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">  
  9.     <!-- rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)-->  
  10.     <!-- cipherKey是加密rememberMe Cookie的密钥;默认AES算法 -->  
  11.     <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>  
  12.     <property name="cookie" ref="rememberMeCookie"/>  
  13. </bean>  
  14.   
  15. <!-- 会话管理器相关 -->  
  16. <!-- 会话Cookie模板-->  
  17. <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
  18.     <constructor-arg value="sessionId"/>  
  19.     <property name="httpOnly" value="true"/>  
  20.     <property name="maxAge" value="-1"/><!--maxAge=-1表示浏览器关闭时失效此Cookie-->  
  21. </bean>  
  22. <!-- 会话ID生成器 -->  
  23. <bean id="sessionIdGenerator"  
  24.       class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>  
  25. <!-- 会话DAO -->  
  26. <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">  
  27.     <!-- 设置Session缓存名字,默认就是shiro-activeSessionCache -->  
  28.     <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>  
  29.     <property name="sessionIdGenerator" ref="sessionIdGenerator"/>  
  30. </bean>  
  31. <!-- 会话验证调度器 -->  
  32. <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">  
  33.     <property name="sessionValidationInterval" value="1800000"/><!--设置调度时间间隔 半小时  默认值为1小时-->  
  34.     <property name="sessionManager" ref="sessionManager"/>  
  35. </bean>  
  36. <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
  37.     <property name="globalSessionTimeout" value="1800000"/> <!-- 设置全局会话超时时间 半小时 -->  
  38.     <property name="deleteInvalidSessions" value="true"/> <!-- 删除过期的会话 -->  
  39.     <property name="sessionValidationSchedulerEnabled" value="true"/> <!-- 是否开启会话验证器 默认开启 -->  
  40.     <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/> <!-- 设置会话调度器 -->  
  41.     <property name="sessionDAO" ref="sessionDAO"/>  
  42.     <!-- 是否启用Session Id Cookie,默认是启动;如果是禁用则默认使用servlet容器的 JSESSIONID -->  
  43.     <property name="sessionIdCookieEnabled" value="true"/>  
  44.     <property name="sessionIdCookie" ref="sessionIdCookie"/>  
  45. </bean>  
  46. <!-- 配置安全管理器 -->  
  47. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
  48.     <property name="realm" ref="myRealm"/>  
  49.     <property name="cacheManager" ref="shiroEncacheManager"/>  
  50.     <property name="rememberMeManager" ref="rememberMeManager"/>  
  51.     <property name="sessionManager" ref="sessionManager"/><!--会话管理-->  
  52. </bean>  
  53. <!-- 静态注入,相当于调用SecurityUtils.setSecurityManager(securityManager) -->  
  54. <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  55.     <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>  
  56.     <property name="arguments" ref="securityManager"/>  
  57. </bean>  

3 设置Shiro过滤器

注意:有顺序优先级,匿名的url配置要放在有登录或者用户限制的前面
[html]  view plain  copy
  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.     <!-- Shiro的核心安全接口,这个属性是必须的 -->  
  3.     <property name="securityManager" ref="securityManager"/>  
  4.     <!-- 身份认证失败,则跳转到登录页面的配置 -->  
  5.     <!--<property name="loginUrl" value="/jsp/login.jsp"/>-->  
  6.     <property name="loginUrl" value="/authority/notLogin"/>  
  7.     <!-- 权限认证失败,则跳转到指定页面 -->  
  8.     <!--<property name="unauthorizedUrl" value="/jsp/noAccess.jsp"/>-->  
  9.     <property name="unauthorizedUrl" value="/authority/noAccess"/>  
  10.     <!-- Shiro连接约束配置,即过滤链的定义 -->  
  11.     <property name="filterChainDefinitions">  
  12.         <!--过滤定义,从上而下,蒋匿名的anon放最下面,小心配置,否则容易出现页面重定向死循环-->  
  13.         <value>  
  14.             <!--anon 表示匿名访问,不需要认证以及授权-->  
  15.             <!--静态资源-->  
  16.             /js/**=anon  
  17.             /css/**=anon  
  18.             /img/**=anon  
  19.             /lib/**=anon  
  20.   
  21.             <!--登录注册入口-->  
  22.             /authority/signup*=anon  
  23.             /jsp/login*=anon  
  24.             /authority/login*=anon  
  25.             /authority/notLogin*=anon  
  26.             /authority/noAccess*=anon  
  27.   
  28.             <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->  
  29.             <!--/** = authc-->  
  30.             <!--用户登录时开启了rememberMe,然后他关闭浏览器,下次再访问时他就是一个user,而不会authc-->  
  31.             /jsp/dict*=roles[admin]  
  32.             <!--/user/add=roles[manager]-->  
  33.             <!--/user/del/**=roles[admin]-->  
  34.             <!--/user/edit/**=roles[manager]-->  
  35.             <!--/user=perms[user:del]-->  
  36.             <!--/student=roles[teacher]-->  
  37.             <!--/teacher=perms["user:create"]-->  
  38.   
  39.             /** = user  
  40.         </value>  
  41.     </property>  
  42. </bean>  

4 在springmvcbean中配置拦截器和开启注解功能

[html]  view plain  copy
  1. <!-- 开启Shiro URL权限控制 注解 -->  
  2. <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"  
  3.       depends-on="lifecycleBeanPostProcessor">  
  4.     <property name="proxyTargetClass" value="true"/>  
  5. </bean>  
  6. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
  7.     <property name="securityManager" ref="securityManager"/>  
  8. </bean>  

3 shiro常用示例

1 登录

[java]  view plain  copy
  1. Subject subject = SecurityUtils.getSubject();  
  2. //err.println(LogUtils.format(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt())));  
  3. UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword(), rememberMe);//设置是否保持登录  
  4. try  
  5. {  
  6.     subject.login(token);  
  7.     AuthorityHelper.setCurrentUserEntity(authorityService.getUserByUsername(SecurityUtils.getSubject().getPrincipal().toString()));//自定义工具方法保存当前用户DO  
  8.     //if(WebUtils.getSavedRequest(request) != null)  
  9.     //{  
  10.     //    //配合前端实现登陆前页面跳转  
  11.     //    return WebUtils.getAndClearSavedRequest(request).getRequestUrl();  
  12.     //}  
  13.     //else  
  14.     //{  
  15.     return "登录成功!";  
  16.     //}  
  17. }catch(UnknownAccountException e)  
  18. {  
  19.     e.printStackTrace();  
  20.     throw new RuntimeException("用户名不存在!");  
  21. }catch(ExcessiveAttemptsException e)  
  22. {  
  23.     e.printStackTrace();  
  24.     throw new RuntimeException("登录失败次数过多!10分钟后重试");  
  25.   
  26.   
  27. }catch(IncorrectCredentialsException e)  
  28. {  
  29.     e.printStackTrace();  
  30.     throw new RuntimeException("密码错误!");  
  31. }catch(AuthenticationException e)  
  32. {  
  33.     e.printStackTrace();  
  34.     throw new RuntimeException("登录出错!");  
  35. }  

2 Shiro注解使用

常用注解
  • @RequiresAuthentication : 表示当前Subject已经通过Login进行身份验证
  • @RequiresUser : 表示当前Subject已经身份验证或者通过记住我登录
  • @RequiresGuest : 表示当前Subject已经没有身份验证或通过记住我登录,即是游客身份
  • @RequiresRoles(value={"admin", "user"}, Logical.AND) : 表示当前Subject需要admin和user角色
  • @RequiresPermissions(value={"user:a", "user:b"}) : 表示当前Subject需要权限user:a或user:b
最常用的是@RequiresPermissions和@RequiresRoles,加在controler类上(把每个url看成是需要控制权限的资源)
一般Authentication或者User(这两个区别是是否通过通过“
住我 ”登录 )会在过滤器的url中统一限制
关于如何限制权限,简单的直接通过RequiresRoles批量限制,如果是具体某个权限则通过RequiresPermissions来限制
理论上最好的方式是面向资源进行权限限制(即使用RequiresPermissions给不同资源设置权限)然后根据角色分配资源(设置权限),这样便于动态控制(用户表,角色表,资源权限表,角色资源权限表),参考http://globeeip.iteye.com/blog/1236167

3会话管理

[java]  view plain  copy
  1. 当前会话  
  2. Subject.getSession();  
  3. //获取会话,默认为Subject.getSession(true)即当前没有创建Session则会创建,   
  4. Subject.getSession(false)即当前没有Session返回NULL  
  5. session.getId(); //获取当前会话的唯一标示  
  6. session.getHost(); //获取当前Subject的主机地址  
  7. session.getTimeout() & session.setTimeout(毫秒);   
  8. //获取/设置当前Session的过期时间  
  9. session.getStartTimestamp() & session.getListAccessTime();   
  10. //获取会话的启动时间以及最后访问时间,如果是JavaSE应用需要手动定期调用session.touch  
  11. 去更新最后访问时间, 如果是Web应用每次进入ShiroFIlter会自动调用session.touch()进行更新最后访问时间  
  12.   
  13. 所有会话DAO  
  14. 在配置中配置过org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO即可在代码中获取使用  
  15. enterpriseCacheSessionDAO.delete(enterpriseCacheSessionDAO.readSession(sessionId))  

4 区分url访问和ajax请求

返回不同的登录失败或无授权结果(页面或者json数据)
需要真shiro 的springBean中注册过滤器
//身份验证过滤器,区分ajax请求(返回json数据)

<bean id="authenticationFilter" class="com.cetiti.common.web.MyShiroAuthenticationFilter"/>

并在shiro过滤器中配入

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="filters">
    <util:map>
    <entry key="user" value-ref="authenticationFilter"/>
    </util:map>
    </property>
    <!--其他配置这里省略-->
</bean>
MyShiroAuthenticationFilter具体实现如下
主要重写了
onAccessDenied方法,增加了是否是ajax请求的判断逻辑并返回不同结果
[java]  view plain  copy
  1. public class MyShiroAuthenticationFilter extends UserFilter  
  2. {  
  3.     @Data  
  4.     @AllArgsConstructor  
  5.     class UnauthenticatedExceptionInfoType  
  6.     {  
  7.         //返回json数据的格式  
  8.         int statusCode;  
  9.         Date dateTime;  
  10.         String message;  
  11.     }  
  12.     private ObjectMapper objectMapper = new MyJacksonObjectMapper();  
  13.   
  14.     @Override  
  15.     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception  
  16.     {  
  17.         if(isAjax(request))  
  18.         {  
  19.             ((HttpServletResponse) response).setHeader("Content-Type""application/json;charset=utf-8");  
  20.             response.getWriter().print(objectMapper.writeValueAsString(new UnauthenticatedExceptionInfoType(HttpStatus.UNAUTHORIZED.value(), new Date(), "未登录!")));  
  21.         }  
  22.         else  
  23.         {  
  24.             saveRequestAndRedirectToLogin(request, response);  
  25.         }  
  26.         return false;  
  27.     }  
  28.   
  29.     public static boolean isAjax(ServletRequest request)  
  30.     {  
  31.         String header = ((HttpServletRequest) request).getHeader("X-Requested-With");  
  32.         if("XMLHttpRequest".equalsIgnoreCase(header))  
  33.         {  
  34.             return Boolean.TRUE;  
  35.         }  
  36.         return Boolean.FALSE;  
  37.     }  
  38. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值