所谓的验证码登录也就是 验证码正确之后利用shiro的免密登录啦
验证码的验证:发送短信的时候,把验证码信息放到缓存里(key为sessionid),表单提交过来的时候,从缓存里拿出来比较就好。
接下来就是shiro 的免密登录:http://github.crmeb.net/u/defu
1、思路
自定义token,在进行授权时判断是密码登陆或无密码登陆,自定义密码认证方法,即写一个方法继承HashedCredentialsMatcher,重写其中的doCredentialsMatch,将其中的token改写为自定义的token,最后将自己写的密码认证方法注入shiro
2、源码
1、shiro中有一个类HashedCredentialsMatcher,其中doCredentialsMatch为验证密码的方法
2、在ShiroDbRealm中普通登录用的是划红框的UsernamePasswordToken,免密登录的话需要自定义一个Token;
3、免密登录
1)创建一个枚举类
public enum LoginType {
PASSWORD("password"), // 密码登录
NOPASSWD("nopassword"); // 免密登录
private String code;
private LoginType(String code) {
this.code = code;
}
public String getCode () {
return code;
}
}
2)自定义Token
import org.apache.shiro.authc.UsernamePasswordToken;
/**
* 用于免密登录
*/
public class EasyTypeToken extends UsernamePasswordToken {
private static final long serialVersionUID = -775223922389896739L;
private LoginType type;
public EasyTypeToken() {
super();
}
public EasyTypeToken(String username, String password, LoginType type, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
this.type = type;
}
/**免密登录*/
public EasyTypeToken(String username) {
super(username, "", false, null);
this.type = LoginType.NOPASSWD;
}
/**账号密码登录*/
public EasyTypeToken(String username, String password) {
super(username, password, false, null);
this.type = LoginType.PASSWORD;
}
public LoginType getType() {
return type;
}
public void setType(LoginType type) {
this.type = type;
}
}
3)修改ShiroDbRealm:将UsernamePasswordToen修改为自定义token
4)、重写doCredentialsMatch方法,有其他的限定也可以加进去。
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cache.CacheManager;
import org.springframework.util.Assert;
/**
* 输错5次密码锁定半小时
*
* @author QBK
*/
public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher implements InitializingBean {
private CacheManager cacheManager;
private String retryLimitCacheName;
private PasswordHash passwordHash;
public RetryLimitCredentialsMatcher(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public String getRetryLimitCacheName() {
return retryLimitCacheName;
}
public void setRetryLimitCacheName(String retryLimitCacheName) {
this.retryLimitCacheName = retryLimitCacheName;
}
public void setPasswordHash(PasswordHash passwordHash) {
this.passwordHash = passwordHash;
}
/* @Override
public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
String username = (String) authcToken.getPrincipal();
Integer retryCount = getCount(username);
if (retryCount == null) {
retryCount = 1;
} else {
retryCount++;
}
setCount(username, retryCount);
if (retryCount > 5) {
throw new ExcessiveAttemptsException();
}
boolean matches = super.doCredentialsMatch(authcToken, info);
if (matches) {
removeCount(username);
}
return matches;
}*/
@Override
public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
/**
* 免密登录
*/
EasyTypeToken tk = (EasyTypeToken) authcToken;
if(tk.getType().equals(LoginType.NOPASSWD)){
return true;
}else{
/**
* 需要密码登录
*/
return super.doCredentialsMatch(authcToken, info);
}
}
/**
* @param username
*/
private void removeCount(String username) {
cacheManager.getCache(retryLimitCacheName).evict(genKey(username));
}
private void setCount(String username, int retryCount) {
cacheManager.getCache(retryLimitCacheName).put(genKey(username), retryCount);
}
private Integer getCount(String username) {
return cacheManager.getCache(retryLimitCacheName).get(genKey(username),Integer.class);
}
private String genKey(String username) {
return retryLimitCacheName + username;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(passwordHash, "you must set passwordHash!");
super.setHashAlgorithmName(passwordHash.getAlgorithmName());
super.setHashIterations(passwordHash.getHashIterations());
}
}
加到配置里面
5)密码登录:
Subject user = SecurityUtils.getSubject();
EasyTypeToken token = new EasyTypeToken(username, password);
user.login(token);
免密登录:
Subject user = SecurityUtils.getSubject();
EasyTypeToken token = new EasyTypeToken(username);
user.login(token);