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