这里只用MD5加盐的方式对密码进行加密,为了提高安全性,盐值采用的是用户名+一个从数据库中获取的字段salt
密码比对的逻辑是在QueryDatabaseAuthenticationHandler
的authenticateUsernamePasswordInternal
方法中,因此加密操作如下:
1.自定义一个类MyQueryDatabaseAuthenticationHandler
该类与QueryDatabaseAuthenticationHandler
基本相同
原类的写法是
@Component("queryDatabaseAuthenticationHandler")
public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
@NotNull
private String sql;
@Override
protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
throws GeneralSecurityException, PreventedException {
if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) {
throw new GeneralSecurityException("Authentication handler is not configured correctly");
}
final String username = credential.getUsername();
final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword());
try {
final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
if (!dbPassword.equals(encryptedPassword)) {
throw new FailedLoginException("Password does not match value on record.");
}
} catch (final IncorrectResultSizeDataAccessException e) {
if (e.getActualSize() == 0) {
throw new AccountNotFoundException(username + " not found with SQL query");
} else {
throw new FailedLoginException("Multiple records found for " + username);
}
} catch (final DataAccessException e) {
throw new PreventedException("SQL exception while executing query for " + username, e);
}
return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null);
}
/**
* @param sql The sql to set.
*/
@Autowired
public void setSql(@Value("${cas.jdbc.authn.query.sql:}") final String sql) {
this.sql = sql;
}
@Override
@Autowired(required = false)
public void setDataSource(@Qualifier("queryDatabaseDataSource") final DataSource dataSource) {
super.setDataSource(dataSource);
}
}
由于盐值的一部分是从数据库中获取的,因此添加一个saltSql
字段,用于存放获取salt的sql,并添加了它的setSaltSql
方法
@Component("myQueryDatabaseAuthenticationHandler")
public class MyQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
@NotNull
private String sql;
@NotNull
private String saltSql;
@Override
protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
throws GeneralSecurityException, PreventedException {
if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) {
throw new GeneralSecurityException("Authentication handler is not configured correctly");
}
final String username = credential.getUsername();
//获取用户输入的密码
final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword());
try {
//获取数据库中的密码
final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
//获取盐值
final String salt = username + getJdbcTemplate().queryForObject(this.saltSql, String.class, username);
//使用Md5Hash的构造方法将用户输入的密码进行加密,加密次数为2
String md5Pwd = new Md5Hash(encryptedPassword,salt,2).toHex();
if (!dbPassword.equals(md5Pwd)) {
throw new FailedLoginException("Password does not match value on record.");
}
} catch (final IncorrectResultSizeDataAccessException e) {
if (e.getActualSize() == 0) {
throw new AccountNotFoundException(username + " not found with SQL query");
} else {
throw new FailedLoginException("Multiple records found for " + username);
}
} catch (final DataAccessException e) {
throw new PreventedException("SQL exception while executing query for " + username, e);
}
return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null);
}
/**
* @param sql The sql to set.
*/
@Autowired
public void setSql(@Value("${cas.jdbc.authn.query.sql:}") final String sql) {
this.sql = sql;
}
/**
* @param saltSql The saltSql to set.
*/
@Autowired
public void setSaltSql(@Value("${cas.jdbc.authn.query.saltSql:}") final String saltSql) {
this.saltSql = saltSql;
}
@Override
@Autowired(required = false)
public void setDataSource(@Qualifier("queryDatabaseDataSource") final DataSource dataSource) {
super.setDataSource(dataSource);
}
}
2.修改cas-server-webapp下的deployerConfigContext.xml
添加
<bean id="myQueryDatabaseAuthenticationHandler" class="org.jasig.cas.adaptors.jdbc.MyQueryDatabaseAuthenticationHandler"
p:dataSource-ref="dataSource"
p:sql="select password from test_a where name = ?"
p:saltSql="select salt from test_a where name = ?"/>
test_a为用户表表名,name为用户名字段,password为密码字段,salt为盐值字段
修改
<alias name="queryDatabaseAuthenticationHandler" alias="primaryAuthenticationHandler" />
改为
<alias name="myQueryDatabaseAuthenticationHandler" alias="primaryAuthenticationHandler" />