目录
Shiro的会话管理具备Tomcat的会话管理的一切功能
相较于Tomcat的session,shiro提供了对于分布式session的管理
当我们在使用一个项目时是多个的数据访问量的,所以肯定会配置多个Tomcat服务器进行交互,但是我们无法确定我们每次请求的都是同一个Tomcat,也就没办法保证我们的session存值能够正确拿到。
所以我们采用Shiro会话来存值原本存放在Tomcat上面的值(图示)
- package com.zq.ssm.shiro;
-
- import org.apache.shiro.session.Session;
- import org.apache.shiro.session.SessionListener;
-
- public class MysessionListener implements SessionListener {
- @Override
- public void onStart(Session session) {
- System.out.println("ShiroSessionListener.onStart..."+session.getId());
- }
-
- @Override
- public void onStop(Session session) {
- System.out.println("ShiroSessionListener.onStop..."+session.getId());
- }
-
- @Override
- public void onExpiration(Session session) {
- System.out.println("ShiroSessionListener.onExpiration..."+session.getId());
- }
- }
-
- <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
-
-
- <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
- <property name="realm" ref="shiroRealm" />
- <property name="sessionManager" ref="sessionManager">property>
- bean>
-
-
- <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator">
- bean>
-
-
- <bean id="customSessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
- <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
- bean>
-
-
- <bean id="shiroSessionListener" class="com.zq.ssm.shiro.MysessionListener"/>
-
-
- <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
-
- <constructor-arg value="shiro.session"/>
-
- <property name="maxAge" value="-1"/>
-
- <property name="httpOnly" value="true"/>
- bean>
-
-
- <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
-
- <property name="globalSessionTimeout" value="120000"/>
-
- <property name="sessionDAO" ref="customSessionDao"/>
-
- <property name="sessionValidationInterval" value="60000"/>
-
-
-
-
-
- <property name="deleteInvalidSessions" value="true"/>
-
- <property name="sessionListeners">
- <list>
- <ref bean="shiroSessionListener"/>
- list>
- property>
-
- <property name="sessionIdCookie" ref="sessionIdCookie"/>
-
- <property name="sessionIdUrlRewritingEnabled" value="false"/>
- bean>
当登录发送请求 会执行 监听器中的 onstart
当登出发送请求 会执行 监听器中的 onStop
当检查session过期时,会执行 监听器中的 onExpiration
过期时,需要身份验证才能访问的方法,就不会被允许访问;
在没有使用缓存的情况下,我们每次发送请求都会调用一次doGetAuthorizationInfo方法来进行用户的授权操作,但是我们知道,一个用户具有的权限一般不会频繁的修改,也就是每次授权的内容都是一样的,所以我们希望在用户登录成功的第一次授权成功后将用户的权限保存在缓存中,下一次请求授权的话就直接从缓存中获取,这样效率会更高一些。
Ehcache是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大。是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
- <dependency>
- <groupId>net.sf.ehcachegroupId>
- <artifactId>ehcacheartifactId>
- <version>${ehcache.version}version>
- dependency>
-
-
- <dependency>
- <groupId>org.slf4jgroupId>
- <artifactId>slf4j-apiartifactId>
- <version>${slf4j-api.version}version>
- dependency>
- <dependency>
- <groupId>org.slf4jgroupId>
- <artifactId>jcl-over-slf4jartifactId>
- <version>${slf4j-api.version}version>
- <scope>runtimescope>
- dependency>
- "1.0" encoding="UTF-8"?>
- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
- updateCheck="false">
-
-
-
- <diskStore path="D://xxx"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
- <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
- timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
-
-
-
- <cache name="com.javaxl.one.entity.User" eternal="false" maxElementsInMemory="100"
- overflowToDisk="true" diskPersistent="true" timeToIdleSeconds="0"
- timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
- ehcache>
- package com.zq.ssm.util;
-
-
- import net.sf.ehcache.Cache;
- import net.sf.ehcache.CacheManager;
- import net.sf.ehcache.Element;
-
- import java.io.InputStream;
-
- public class EhcacheUtil {
-
- private static CacheManager cacheManager;
-
-
-
- static {
- try {
- InputStream is = EhcacheUtil.class.getResourceAsStream("/ehcache.xml");
- cacheManager = CacheManager.create(is);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private EhcacheUtil() {
- }
-
- public static void put(String cacheName, Object key, Object value) {
- Cache cache = cacheManager.getCache(cacheName);
- if (null == cache) {
- //以默认配置添加一个名叫cacheName的Cache
- cacheManager.addCache(cacheName);
- cache = cacheManager.getCache(cacheName);
- }
- cache.put(new Element(key, value));
- }
-
-
- public static Object get(String cacheName, Object key) {
- Cache cache = cacheManager.getCache(cacheName);
- if (null == cache) {
- //以默认配置添加一个名叫cacheName的Cache
- cacheManager.addCache(cacheName);
- cache = cacheManager.getCache(cacheName);
- }
- Element element = cache.get(key);
- return null == element ? null : element.getValue();
- }
-
- public static void remove(String cacheName, Object key) {
- Cache cache = cacheManager.getCache(cacheName);
- cache.remove(key);
- }
- }
- package com.zq.ssm.shiro;
-
- import com.zq.ssm.biz.UserBiz;
- import com.zq.ssm.model.User;
- import com.zq.ssm.util.EhcacheUtil;
- 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.authz.AuthorizationInfo;
- import org.apache.shiro.authz.SimpleAuthorizationInfo;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.util.ByteSource;
-
- import java.util.Set;
-
-
- public class MyRealm extends AuthorizingRealm{
-
- private UserBiz userBiz;
-
- public UserBiz getUserBiz() {
- return userBiz;
- }
-
- public void setUserBiz(UserBiz userBiz) {
- this.userBiz = userBiz;
- }
-
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
-
- System.out.println("用户授权。。。");
- String username = principals.getPrimaryPrincipal().toString();
- //先从缓存中 缓存中没有,在查询数据库 查询出数据放入缓存
- String cacheName1 = "user:role:"+username;
- String cacheName2 = "user:per:"+username;
- //转成字符形式
- //用户
- //User user = userBiz.queryByName(username);
- //拿到角色id
- //从缓存中获取角色
- Set
roleIds = (Set) EhcacheUtil.get(cacheName1,username); - //拿到角色权限
- //从缓存中获取权限
- Set
perIds = (Set) EhcacheUtil.get(cacheName2,username); -
- if(roleIds==null||roleIds.size()==0){
- roleIds = userBiz.getPersByUserId(username);
- System.out.println("从数据库中读取用户角色。。。。");
- }
-
- if(perIds==null||perIds.size()==0){
- perIds = userBiz.getPersByUserId(username);
- System.out.println("从数据库中读取用户权限。。。。");
- }
-
- //授权
- SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
- //角色
- info.setRoles(roleIds);
- //权限
- info.setStringPermissions(perIds);
-
- return info;
- }
-
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- System.out.println("身份认证...");
- String username = token.getPrincipal().toString();
- //String password = token.getCredentials().toString();
- User user = userBiz.queryByName(username);
- // 拿到数据库中的用户信息,放入token凭证中,用于controler进行对比
- AuthenticationInfo info = new SimpleAuthenticationInfo(
- user.getUsername(),
- user.getPassword(),
- ByteSource.Util.bytes(user.getSalt()),
- this.getName()
- );
- return info;
- }
- }