【Java】SpringMVC项目利用Shiro设置固定时间内密码登录重试次数限制
来源:互联网 发布:usleep函数 linux 编辑:程序博客网 时间:2024/05/19 14:20
1.pom配置:
<!-- shiro --><dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.4.0</version></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.4.0</version></dependency><dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version></dependency> <!-- shiro end -->
- ecache.xml
<?xml version="1.0" encoding="UTF-8"?><ehcache name="shirocache"> <diskStore path="java.io.tmpdir"/> <!-- 登录记录缓存 锁定10分钟 --> <cache name="passwordRetryCache" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> </ehcache>
3.application-spring-shiro.xml配置
<?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:p="http://www.springframework.org/schema/p"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/cachehttp://www.springframework.org/schema/cache/spring-cache-4.0.xsd"> <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 调用我们配置的权限管理器 --> <property name="securityManager" ref="securityManager"/> <!-- 配置我们的登录请求地址 --> <property name="loginUrl" value="/"/> <!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 --> <!-- <property name="successUrl" value="/"/> --> <!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 --> <property name="unauthorizedUrl" value="/pages/error403.jsp"/> <!-- 权限配置 --> <property name="filterChainDefinitions"> <value> <!-- anon表示此地址不需要任何权限即可访问 --> <!-- perms[user:query]表示访问此连接需要权限为user:query的用户 --> <!-- roles[manager]表示访问此连接需要用户的角色为manager --> /static/**=anon /about/*=anon /logins/*=anon /pages/error403.jsp=anon /pages/login.jsp=anon /pages/index.jsp=anon /pages/menu/menulist.jsp=perms[user:view] <!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/--> /** = authc </value> </property> </bean> <!-- 缓存管理器 使用Ehcache实现 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache/ehcache.xml"/> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- ref对应我们写的realm MyShiro --> <property name="realms" > <list><ref bean="SimpleRealm"/></list> </property> <!-- 使用下面配置的缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 配置进行授权和认证的 Realm --> <bean id="SimpleRealm" class="com.naton.shiro.SimpleRealm" init-method="initCredentialsMatcher"> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 配置 Bean 后置处理器: 会自动的调用和 Spring 整合后各个组件的生命周期方法. --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- Support Shiro Annotation --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean></beans>
4.关键地方的代码编写:
package com.naton.shiro;import javax.annotation.PostConstruct;import org.apache.shiro.SecurityUtils;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.session.Session;import org.apache.shiro.subject.PrincipalCollection;import com.naton.pojo.po.UserInfo;import org.apache.shiro.cache.CacheManager;public class SimpleRealm extends AuthorizingRealm {private CacheManager cacheManager;public CacheManager getCacheManager() {return cacheManager;}public void setCacheManager(CacheManager cacheManager) {this.cacheManager = cacheManager;}/** * 初始化密码部分验证条件 */ public void initCredentialsMatcher() {//该句作用是重写shiro的密码验证,让shiro用自定义的验证 CustomCredentialsMatcher customCredentialsMatcher = new CustomCredentialsMatcher(cacheManager); setCredentialsMatcher(customCredentialsMatcher); }/** * 认证 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {CustomToken token = (CustomToken) authenticationToken; SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( token.getPrincipal(), //用户名 token.getCredentials(), //密码 getName() //realm name );return authenticationInfo;}/** * 授权 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();Session session = SecurityUtils.getSubject().getSession();UserInfo user = (UserInfo) session.getAttribute("currentUser");if (user != null) {//通过用户名从数据库获取权限字符串authorizationInfo.setStringPermissions(user.getPermissions());} return authorizationInfo;}}
package com.naton.shiro;import java.util.concurrent.atomic.AtomicInteger;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;import org.apache.shiro.cache.Cache;import com.naton.advice.exception.ServiceException;import org.apache.shiro.cache.CacheManager;/** * 自定义 密码验证类 * * @author q * */public class CustomCredentialsMatcher extends SimpleCredentialsMatcher { //private Ehcache passwordRetryCache;private Cache<String,AtomicInteger> passwordRetryCache;public CustomCredentialsMatcher(CacheManager cacheManager) { passwordRetryCache = cacheManager.getCache("passwordRetryCache"); } @Override public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; String loginName = token.getUsername();String pwd = String.valueOf(token.getPassword());AtomicInteger retryCount = passwordRetryCache.get(loginName);if(retryCount==null){retryCount = new AtomicInteger();passwordRetryCache.put(loginName, retryCount);}if(retryCount.incrementAndGet()>5){ //throw new ExcessiveAttemptsException();throw new ServiceException(0,"输入错误次数已经达到5次");}//假设的一个验证机制 int resp;try {resp = Integer.parseInt(pwd);} catch (Exception e) {resp = 0;}if(resp == 1){//clear retry countpasswordRetryCache.remove(loginName); return true;}else{return false;} }public Cache<String, AtomicInteger> getPasswordRetryCache() {return passwordRetryCache;}public void setPasswordRetryCache(Cache<String, AtomicInteger> passwordRetryCache) {this.passwordRetryCache = passwordRetryCache;} }
知行办公,专业移动办公平台 https://zx.naton.cn/原创团队【总监】十二春秋之,3483099@qq.com;【Master】zelo,616701261@qq.com;【运营】运维艄公,897221533@qq.com;【产品设计】流浪猫,364994559@qq.com;【体验设计】兜兜,2435632247@qq.com;【iOS】淘码小工,492395860@qq.com;iMcG33K,imcg33k@gmail.com;【Android】人猿居士,1059604515@qq.com;思路的顿悟,1217022114@qq.com;【java】首席工程师MR_W,feixue300@qq.com;【测试开发】土镜问道,847071279@qq.com;【数据】fox009521,42151960@qq.com;【安全】保密,你懂的。
阅读全文