天天看點

shiro免密碼登入

傳統的登入方式都是使用者名和密碼組合登入,但是現在輔助登入手段多樣,比如短信驗證碼,郵箱驗證碼等其他手段。這樣就無法擷取密碼進行驗證。是以本文整理了不需要密碼的認證方式。

 傳統的登入代碼如下

UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
        Subject subject = SecurityUtils.getSubject();
    
        Map userMap = new HashMap();
        try {
            //使用shiro 進行登入認證
            subject.login(token);
            
    
        } catch (UnknownAccountException uae) {
            subject.getSession().removeAttribute(LoginString.LOGIN_KEY);
            returnBean = new ReturnBean(uae, "使用者名不存在");

        } catch (IncorrectCredentialsException e) {
            subject.getSession().removeAttribute(LoginString.LOGIN_KEY);
            returnBean = new ReturnBean(e, "密碼錯誤");
 
        } catch (AuthenticationException e) {
            // 賬戶認證失敗
            subject.getSession().removeAttribute(LoginString.LOGIN_KEY);
            returnBean = new ReturnBean(e, "賬戶認證失敗");
        } catch (Exception e) {
            Logger.error("登入異常{}" + ExceptionUtils.getStackTrace(e));
            returnBean = new ReturnBean(e, "登入異常");
        }
     
  
           

上述代碼中我們用的認證的類是UsernamePasswordToken ,為了免密登入,需要重寫UsernamePasswordToken類,如下

import org.apache.shiro.authc.UsernamePasswordToken;

public class NewUsernameToken extends UsernamePasswordToken {


    private static final long serialVersionUID =1L;

    private boolean type;


    public NewUsernameToken() {
        super();
    }


    public NewUsernameToken(String username, String password, boolean rememberMe, String host) {
        super(username, password, rememberMe,host);
        this.type = false;
    }
    /**免密登入*/
    public NewUsernameToken(String username) {
        super(username, "", false, null);
        this.type = true;
    }
    /**賬号密碼登入*/
    public NewUsernameToken(String username, String password) {
        super(username, "", false, null);
        this.type = false;
    }

    public boolean isType() {
        return type;
    }

    public void setType(boolean type) {
        this.type = type;
    }
}
           

修改原登入代碼

NewUsernameToken token = new NewUsernameToken(username);
           

還需要重寫一下HashedCredentialsMatcher類的doCredentialsMatch方法

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;

public class MyHashedCredentialsMatcher extends HashedCredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        NewUsernameToken et = (NewUsernameToken)token;
        if(et.isType()){
            return true;
        }
        Object tokenHashedCredentials = hashProvidedCredentials(token, info);
        Object accountCredentials = getCredentials(info);
        return equals(tokenHashedCredentials, accountCredentials);
    }

}
           

最後在shiro的配置中引用該類

/**
     * 自定義登陸認證
     * @return
     */
    @Bean
    public MyRealm myShiroRealm() {
        MyRealm myShiroRealm = new MyRealm();
        //憑證比對
        MyHashedCredentialsMatcher credentialsMatcher = new MyHashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(2);
        myShiroRealm.setCredentialsMatcher(credentialsMatcher);
        return myShiroRealm;
    }
           

最最後一步

//免密登入,這裡傳啥都無所謂
		AuthenticationInfo info = new SimpleAuthenticationInfo("AA", "AA",
				ByteSource.Util.bytes("AA"), getName());
           

上述代碼是重寫了AuthorizingRealm類中的doGetAuthenticationInfo方法。這樣免密登入就成功了。