shiro教程:整合ehcache缓存

这个是在ssm的基础上再去整合shiro和ehcache的,整合ehcache主要是为了减少后台shiro拦截的次数,因为如果我们不使用缓存的话,后台shiro的认证和授权的拦截器就会反复的进行拦截,导致系统的运行效率不高,因此使用缓存是一种很好的解决的方法,下面我们看看如何整合ehcache。

1、加入jar包pom.xml

在这之前,我们先加入shiro和ehcache的相关jar包

<!-- shiro -->
		<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

2、配置ehcache.xml配置文件

在整合之前,我们需要配置一下ehcache的一些参数,设置好ehcache的环境。

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache">

	<diskStore path="C:\shiro\ehcache" />
<!-- 	<diskStore path="java.io.tmpdir"/> -->

	<!--   
    eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。  
    maxElementsInMemory:缓存中允许创建的最大对象数  
    overflowToDisk:内存不足时,是否启用磁盘缓存。  
    timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,  两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是 0 就意味着元素可以停顿无穷长的时间。  
    timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。  
    memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。  
    diskPersistent:设定在虚拟机重启时是否进行磁盘存储,默认为false
    diskExpiryThreadIntervalSeconds: 属性可以设置该线程执行的间隔时间(默认是120秒,不能太小
    1 FIFO,先进先出  
    2 LFU,最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。  
    3 LRU,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。  
    -->  
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />

	<cache name="activeSessionCache"
           maxElementsInMemory="10000"
           eternal="true"
           overflowToDisk="false"
           diskPersistent="true"
           diskExpiryThreadIntervalSeconds="600"/>
           
    <cache name="shiro.authorizationCache"
           maxElementsInMemory="100"
           eternal="false"
           timeToLiveSeconds="600"
           overflowToDisk="false"/>
           
</ehcache>

3、整合spring

整合spring其实很简单的,以前总觉得是一个很复杂的事情一样,每次什么都要整合spring,其实spring就是一个容器,再说的直白点,就是一个map类似的容器,然后通过对容器的操作来实现,因此,如果我们需要让spring来管理ehcache的话,我们只是需要将ehcache的配置文件交给spring来管理即可。

下面就是spring的配置文件applicationContext-ehcache.xml的ehcache的配置

<?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:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd ">
  
   <!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="userRealm" />
		<property name="cacheManager" ref="cacheManager"/>
	</bean>
 
     <!-- 缓存管理器 -->
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
	    	<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
        </bean>
</beans>

4、缓冲清空

当用户权限修改后,用户再次登陆shiro会自动调用realm从数据库获取权限数据,如果在修改权限后想立即清除缓存则可以调用realm的clearCache方法清除缓存。

realm中定义clearCached方法:

@Component
public class ShiroDBRealm extends AuthorizingRealm {
	/**
	 * 
	 * @Description: 权限修改生效后,立即刷新清空缓存,则可以实现用户不退出生效新的权限
	 * 
	 * @author sihai
	 * @date 2017年9月29日 下午9:34:07
	 */
	public void clearCache() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		super.clearCache(principals);
	}
}

5、测试是否整合成功

@Component
public class ShiroDBRealm extends AuthorizingRealm {
	
	@Autowired
	private UserService userService; 
	
	public ShiroDBRealm(CacheManager cacheManager) {
        super(cacheManager);
    }
	
	/**
	 * 用于登录认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		
		// 1. 从token中获取用户在表单中输入的域,即 用户名 以及 密码,以此来和数据库中的用户真实数据进行匹配
		UsernamePasswordToken userToken = (UsernamePasswordToken)token;
		String username = userToken.getUsername();							// 用户的登录名
		String password = String.valueOf(userToken.getPassword());			// 用户的密码
		
		// 2. 根据用户输入的用户名和数据库进行匹配,查询数据库中的用户,如果查询不到,则返回一个null
		SysUser user = userService.queryUserByUsername(username);
		
		// 3. 判断数据库中查询出来的用户是否存在,不存在代表用户名密码错误;如果存在,则返回 AuthenticationInfo
		if (user == null) {
			return null;
		}
		
		String dbPassword = user.getPassword();
		String dbSalt = user.getAuthSalt();
		String userPassword = ShiroPasswordUtil.getShiroPassword(password, dbSalt, 2);
		
		if (!userPassword.equals(dbPassword)) {
			// 抛出一个异常,密码不正确
			throw new IncorrectCredentialsException();
		}
		
		ActiveUser activeUser = new ActiveUser();
		activeUser.setUserId(user.getId());
		activeUser.setUsername(user.getUsername());
		
		// 4. 返回AuthenticationInfo
		// 参数意义:
		// Object principal: 用户对象,可以使一个对象类,或者一个字符串,存与session中 
		// Object credentials:密码 			
		// 							题外话:我们目前直接根据用户名密码来查询,所以这里直接放用户输入的密码即可;但是,也可疑直接用用户名来查询数据库中的用户,再然后进行密码的比对,如此则此处应该填写用户输入的密码
		// String realmName:当前我们自定义realm的名称
		AuthenticationInfo info = new SimpleAuthenticationInfo(activeUser, password, getName());
		return info;
	}
	
	/**
	 * 用于授权鉴权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		
		// 从principals中获取当前用户
		ActiveUser sessionUser = (ActiveUser)principals.getPrimaryPrincipal();
		String userid = sessionUser.getUserId();
		
		// 模拟从数据库中获取用户的权限(资源权限字符串)
		List<SysPermission> permissionList = null;
		try {
			permissionList = userService.findPermissionListByUserId(userid);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		List<String> percodeList = new ArrayList<String>();
		for (SysPermission p : permissionList) {
			percodeList.add(p.getPercode());
		}
		
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addStringPermissions(percodeList);
		
		return simpleAuthorizationInfo;
	}
}

上面登录认证和授权的代码,当我们没有加入ehcache缓存的时候,我们前台每次授权认证的时候,我们都会访问这段代码,如果当我们只会第一次访问,后面不再访问的时候,说明整合成功了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello-java-maker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值