使用Shiro1.2中的PasswordService實(shí)現(xiàn)密碼加密存儲和比對在Shiro之前的版本中,密碼加密一般采用如下代碼:[java]
view plaincopyString digestString = new Sha256Hash(password, salt, numIterations).toBase64();
密碼比對一般采用HashedCredentialsMatcher或Sha256CredentialsMatcher等相關(guān)比對類,在新版1.2中,增添了一項(xiàng)重要的功能就是密碼服務(wù),使得加密和比對更加方便。
比如:
加密就只需要密碼這個參數(shù)[java]
view plaincopyPasswordService svc = new DefaultPasswordService();
svc.encryptPassword(password);
比對就用如下語句:encrypted是密文[java]
view plaincopysvc.passwordsMatch(password, encrypted);
看到上述代碼,一個感覺就是:程序邏輯很清晰。
同樣的,在1.2中,同樣可以通過密碼服務(wù)配置,實(shí)現(xiàn)與jdbc中的密碼密文進(jìn)行比對。直接上代碼了:
以下是shiro.ini
[plain]
view plaincopypasswordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = com.helloweb.shm.PasswordMatcherEx
passwordMatcher.passwordService = $passwordService
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = 192.168.1.101
ds.user = root
ds.password =******
ds.databaseName = helloweb
ds.url = jdbc:mysql://192.168.1.101:3306/helloweb
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.authenticationQuery = SELECT password FROM user WHERE username = ?
jdbcRealm.dataSource = $ds
jdbcRealm.credentialsMatcher = $passwordMatcher
authc.loginUrl=/login.jsp
[urls]
/admin/**=authc
說明,com.helloweb.shm.PasswordMatcherEx是我對org.apache.shiro.authc.credential.PasswordMatcher進(jìn)行了修正,重寫了getStoredPassword()方法,如下:
[java]
view plaincopypackage com.helloweb.shm;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.credential.PasswordMatcher;
public class PasswordMatcherEx extends PasswordMatcher {
@Override
protected Object getStoredPassword(AuthenticationInfo storedAccountInfo) {
Object stored = super.getStoredPassword(storedAccountInfo);
if (stored instanceof char[]) {
stored = String.valueOf((char[]) stored);
}
return stored;
}
}
重寫的原因是,JdbcRealm返回給PasswordMatcher的哈希值被保存為char[]型,而PasswordMatcher 卻希望getCredentials()返回一個String或Hash。
用戶登錄代碼如下:
[java]
view plaincopypublic String doLogin() {
Subject currentuser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,
password);
try {
if (currentuser.isAuthenticated())
currentuser.logout();
currentuser.login(token);
return SUCCESS;
} catch (Exception e) {
addActionError("用戶名或密碼有誤");
return ERROR;
}
}
用戶注冊代碼如下:
[java]
view plaincopypublic String doReg() {
if (isLegal()) {
User user = new User();
PasswordService svc = new DefaultPasswordService();
String encrypted = svc.encryptPassword(password);
user.setUsername(username);
user.setPassword(encrypted);
UserDAO ud = new UserDAO();
if (!ud.findByUsername(username).isEmpty()) {
addActionError("用戶名已存在!");
return ERROR;
}
ud.save(user);
addActionMessage("注冊成功!");
} else {
addActionError("注冊信息填寫有誤!");
return ERROR;
}
return SUCCESS;
}