CAS 4.2.1单点登录(四) 密码加密之MD5加盐

这里只用MD5加盐的方式对密码进行加密,为了提高安全性,盐值采用的是用户名+一个从数据库中获取的字段salt

密码比对的逻辑是在QueryDatabaseAuthenticationHandlerauthenticateUsernamePasswordInternal方法中,因此加密操作如下:

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" />

猜你喜欢

转载自blog.csdn.net/weixin_39463716/article/details/86095574
今日推荐