shiro配置文件:shiro.ini
[main] credentialsMatcher=com.github.zhangkaitao.shiro.chapter6.credentials.RetryLimitHashedCredentialsMatcher credentialsMatcher.hashAlgorithmName=md5 credentialsMatcher.hashIterations=2 credentialsMatcher.storedCredentialsHexEncoded=true userRealm=com.github.zhangkaitao.shiro.chapter6.realm.UserRealm userRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$userRealm
自定义验证匹配器RetryLimitHashedCredentialsMatcher
package com.github.zhangkaitao.shiro.chapter6.credentials; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; 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 java.util.concurrent.atomic.AtomicInteger; /** * <p>User: Zhang Kaitao * <p>Date: 14-1-28 * <p>Version: 1.0 */ public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { private Ehcache passwordRetryCache; public RetryLimitHashedCredentialsMatcher() { CacheManager cacheManager = CacheManager.newInstance(CacheManager.class.getClassLoader().getResource("ehcache.xml")); passwordRetryCache = cacheManager.getCache("passwordRetryCache"); } @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { //缓存处理,有则在缓存中取,无则放入缓存中,key:用户名 value:登录次数 String username = (String)token.getPrincipal(); //retry count + 1 Element element = passwordRetryCache.get(username); if(element == null) { element = new Element(username , new AtomicInteger(0)); passwordRetryCache.put(element); } AtomicInteger retryCount = (AtomicInteger)element.getObjectValue(); //登录次数大于5次则抛验证次数超量异常 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; } }
自定义userRealm
package com.github.zhangkaitao.shiro.chapter6.realm; import com.github.zhangkaitao.shiro.chapter6.service.UserService; import com.github.zhangkaitao.shiro.chapter6.service.UserServiceImpl; import com.github.zhangkaitao.shiro.chapter6.entity.User; import org.apache.shiro.authc.*; 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; /** * <p>User: Zhang Kaitao * <p>Date: 14-1-28 * <p>Version: 1.0 */ public class UserRealm extends AuthorizingRealm { private UserService userService = new UserServiceImpl(); @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String)principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(userService.findRoles(username)); authorizationInfo.setStringPermissions(userService.findPermissions(username)); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //根据用户传入的用户名查询用户 User user = userService.findByUsername(username); if(user == null) { throw new UnknownAccountException();//没找到帐号 } if(Boolean.TRUE.equals(user.getLocked())) { throw new LockedAccountException(); //帐号锁定 } //查到的正确用户封装为SimpleAuthenticationInfo //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user.getUsername(), //用户名 user.getPassword(), //密码 ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt getName() //realm name ); return authenticationInfo; } }
缓存配置
<?xml version="1.0" encoding="UTF-8"?> <ehcache name="es"> <diskStore path="java.io.tmpdir"/> <!-- 登录记录缓存 锁定10分钟 --> <cache name="passwordRetryCache" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> </ehcache>
注意:
以上配置了验证信息的加密算法,生成用户存储用户时要保证使用相同的加密手段
/** * 创建用户 * @param user */ public User createUser(User user) { //加密密码 passwordHelper.encryptPassword(user); return userDao.createUser(user); }
public class PasswordHelper { private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); private String algorithmName = "md5"; private final int hashIterations = 2; public void encryptPassword(User user) { user.setSalt(randomNumberGenerator.nextBytes().toHex()); String newPassword = new SimpleHash( algorithmName, user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()), hashIterations).toHex(); user.setPassword(newPassword); } }
相关推荐
使用FORM认证的一个实例,权限使用或运算得到。
【ASP.NET编程知识】在ASP.NET Core中实现一个Token base的身份认证实例.docx
是个基于角色的验证,介绍了forms的用法。是个很不错的例子。如果大家对forms还不知道如何运用,大家下载准没错!
基于forms 的身份验证例子源代码,简单例子
主要介绍了JAVA中的Token 基于Token的身份验证实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
本文介绍了php通过会话控制实现身份验证实例,身份的验证是通过session提交数据的。有需要的朋友可以来了解一下。
TOP应用实例,包括身份验证,这是一个war包,直接拷贝到Tomcat的webapps目录下即可运行。
以前在web端的身份认证都是基于Cookie | Session的身份认证,本篇文章主要介绍了在ASP.NET Core中实现一个Token base的身份认证实例,有兴趣的可以了解一下。
WCF实例(基于X.509证书的身份验证)
基于表单的身份验证看上去复杂,但了解原理后则很简单好用,本例是一个简单示例,却能给你解除所有疑惑。
因为网站使用的是windows集成认证,所以遇到了权限问题,需要输入密码。使操作和用户体验非常不方便,研究了好久没有找到好的方法,最后终于让我踏破铁鞋总结出了下面的方法
TOP应用实例,包括身份验证,这是一个war包,直接拷贝到Tomcat的webapps目录下即可运行。
MSMQ 学习 例子 C# Winform
基于口令的身份认证系统的设计与实现,翟朔,何梦云,本文介绍了数据加密与信息安全技术、身份认证技术,并对EKE协议和CAPTCHA作了较为深入的研究。EKE协议是基于弱口令的密钥交换协议,��
ASP.NET提供了3种认证方式:windows身份验证、Forms验证和Passport验证。 windows身份验证: IIS根据应用程序的设置执行身份验证。要使用这种验证方式,在IIS中必须禁用匿名访问。 Forms验证:用Cookie来保存用户...