Bootstrap

SSM框架下shiro的验证码登录

所谓的验证码登录也就是 验证码正确之后利用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);
;