shiro和ehcache整合

在web项目中整合shiro和ehcache,添加账户锁定功能

有如下配置

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 数据验证 -->
        <property name="realm" ref="shiroRealm" />
        <!-- 会话管理 -->
        <property name="sessionManager" ref="sessionManager"/>
        <!-- 缓存管理 -->
        <property name="cacheManager" ref="cacheManager"/>
        <!-- 记住我 -->
        <property name="rememberMeManager" ref="rememberMeManager" />
</bean>

<!-- 配置加密方式,如果不用配置锁定账户,则用org.apache.shiro.authc.credential.HashedCredentialsMatcher -->
<bean id="credentialsMatcher" class="com.silencer.utils.shiro.RetryHashedCredentialsMatcher">
		<constructor-arg ref="cacheManager"/>
		<!-- 加密3次 -->
		<property name="hashIterations" value="3" />
		<!-- md5方式加密 -->
		<property name="hashAlgorithmName" value="MD5" />
		<!-- 是否存储为16位 -->
		<property name="storedCredentialsHexEncoded" value="true" />
</bean>

<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<property name="cacheManager" ref="ehCacheManager" />
</bean>

<bean id="ehCacheManager"   class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation" value="classpath:ehcache.xml" />
</bean>

自定义 RetryHashedCredentialsMatcher 继承 HashedCredentialsMatcher 类,用于记录登录了多少次;如果不用锁定账户功能,此处直接用 HashedCredentialsMatcher 即可

package com.silencer.utils.shiro;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;

/**
 * @description 登陆次数过多时,账户锁定3分钟.
 * @author Silencer
 * @date 2018-08-21 16:17:21
 * @version v_1.0
 */
public class RetryHashedCredentialsMatcher extends HashedCredentialsMatcher {

	private Cache<String, AtomicInteger> passwordRetryCache;

	public RetryHashedCredentialsMatcher(CacheManager cacheManager) {
		this.passwordRetryCache = cacheManager.getCache("passwordRetryCache");
	}

	@Override
	public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
		String username = (String) token.getPrincipal();
		// retry count + 1
		AtomicInteger retryCount = passwordRetryCache.get(username);
		if (retryCount == null) {
			retryCount = new AtomicInteger(0);
			passwordRetryCache.put(username, retryCount);
		}
		if (retryCount.incrementAndGet() > 5) {
			// if retry count > 5 throw
			throw new ExcessiveAttemptsException();
		}

		boolean matches = super.doCredentialsMatch(token, info);
		if (matches) {
			// clear retry count
			passwordRetryCache.remove(username);
		}
		return matches;
	}

}

这样配置会出现如下异常,网上说因为2.5之后ehcache用了单例模式,ehcache-core换为2.4.8即可,我没有试验成功,

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shiroFilter' defined in class path resource [shiro-config.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAdvisor': Cannot resolve reference to bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' while setting bean property 'transactionAttributeSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor#0' defined in class path resource [shiro-config.xml]: Cannot resolve reference to bean 'securityManager' while setting bean property 'securityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'securityManager' defined in class path resource [shiro-config.xml]: Cannot resolve reference to bean 'shiroRealm' while setting bean property 'realm'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shiroRealm' defined in class path resource [shiro-config.xml]: Cannot resolve reference to bean 'credentialsMatcher' while setting bean property 'credentialsMatcher'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'credentialsMatcher' defined in class path resource [shiro-config.xml]: Cannot resolve reference to bean 'cacheManager' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in class path resource [shiro-config.xml]: Cannot resolve reference to bean 'ehCacheManager' while setting bean property 'cacheManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ehCacheManager' defined in class path resource [shiro-config.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Another CacheManager with same name 'sdjfoasgf' already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.
The source of the existing CacheManager is: InputStreamConfigurationSource [stream=java.io.BufferedInputStream@2fbe6cb9]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:238)
	at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:710)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:535)
	at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:672)
	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:638)
	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:686)
	at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:554)
	at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:499)
	at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:172)
	at javax.servlet.GenericServlet.init(GenericServlet.java:158)
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1188)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1132)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1021)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5085)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5397)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1410)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1400)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

解决方法:在ehCacheManager中添加属性shared即可

<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation" value="classpath:ehcache.xml" />
		<property name="shared" value="true" />
</bean>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值