最近在做前後端分離,登錄認證部分用到了Shiro,配置MD5加鹽加密後,在登錄的時候拋出的以下異常:
java.lang.IllegalArgumentException: Odd number of characters.
at org.apache.shiro.codec.Hex.decode(Hex.java:128) ~[shiro-core-1.3.2.jar:1.3.2]
at org.apache.shiro.codec.Hex.decode(Hex.java:107) ~[shiro-core-1.3.2.jar:1.3.2]
at org.apache.shiro.codec.Hex.decode(Hex.java:95) ~[shiro-core-1.3.2.jar:1.3.2]
at org.apache.shiro.authc.credential.HashedCredentialsMatcher.getCredentials(HashedCredentialsMatcher.java:353) ~[shiro-core-1.3.2.jar:1.3.2]
at org.apache.shiro.authc.credential.HashedCredentialsMatcher.doCredentialsMatch(HashedCredentialsMatcher.java:380) ~[shiro-core-1.3.2.jar:1.3.2]
at org.apache.shiro.realm.AuthenticatingRealm.assertCredentialsMatch(AuthenticatingRealm.java:597) ~[shiro-core-1.3.2.jar:1.3.2]
...
對應Realm的代碼:
public class CustomRealm extends AuthorizingRealm {
@Autowired
UserMapper usermapper;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = String.valueOf(token.getUsername());
String password = String.valueOf(token.getPassword());
// 從數據庫獲取對應用戶名的用戶
User user = usermapper.findByUsername(username);
if (user == null) {
throw new AccountException("不存在此用戶");
}
// 獲取鹽值,即用戶名
ByteSource salt = ByteSource.Util.bytes(username);
return new SimpleAuthenticationInfo(token.getPrincipal(), password, salt, getName());
}
}
錯誤就在最後一句代碼:
return new SimpleAuthenticationInfo(token.getPrincipal(), password, salt, getName());
在這裏直接把明文密碼當成參數傳入了構造器
解決方案:將MD5加密後的密碼傳入構造器
修改後代碼:
public class CustomRealm extends AuthorizingRealm {
@Autowired
UserMapper usermapper;
/**
* 獲取身份驗證信息 Shiro中,最終是通過 Realm 來獲取應用程序中的用戶、角色及權限信息的。
*
* @param authenticationToken
* 用戶身份信息 token
* @return 返回封裝了用戶信息的 AuthenticationInfo 實例
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = String.valueOf(token.getUsername());
// 從數據庫獲取對應用戶名的用戶
User user = usermapper.findByUsername(username);
if (user == null) {
throw new AccountException("不存在此用戶");
}
// 獲取鹽值,即用戶名
ByteSource salt = ByteSource.Util.bytes(username);
//注意,數據庫中的user的密碼必須是要經過md5加密,不然還是會拋出異常!!!!!
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), salt, getName());
}
}