package org.apereo.cas.adaptors.jdbc; import java.security.GeneralSecurityException; import java.util.Base64; import java.util.List; import java.util.Map; import javax.security.auth.login.AccountNotFoundException; import javax.security.auth.login.FailedLoginException; import javax.sql.DataSource; import org.apache.commons.lang3.StringUtils; import org.apereo.cas.authentication.AccountPasswordMustChangeException; import org.apereo.cas.authentication.HandlerResult; import org.apereo.cas.authentication.PreventedException; import org.apereo.cas.authentication.UsernamePasswordCredential; import org.apereo.cas.web.landtool.terra.OjdbcProperties; import org.apereo.cas.web.landtool.utils.Md5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; /** * @author Tanbin * @date 2018-12-12 */ @Component public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler { private String sql; @Autowired private OjdbcProperties properties; private static String m0 = "0"; private static String mIsFirst = "ISFIRSTLOGIN"; @Override protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential, String originalPassword) throws GeneralSecurityException, PreventedException { if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) { throw new GeneralSecurityException("Authentication handler is not configured correctly. No SQL statement or JDBC template is found."); } String username = credential.getUsername(); String password = credential.getPassword(); try { username = new String(Base64.getDecoder().decode(username)); credential.setUsername(username); originalPassword = new String(Base64.getDecoder().decode(originalPassword)); String dbPassword = (String) getJdbcTemplate().queryForObject(this.sql, String.class, new Object[]{username}); //第一次登录,仍使用源方式认证 if (isFirstLogin(username)) { boolean b1 = StringUtils.isNotBlank(originalPassword) && !matches(originalPassword, dbPassword); boolean b2 = StringUtils.isBlank(originalPassword) && !StringUtils.equals(password, dbPassword); if (b1 || b2) { throw new FailedLoginException("Password does not match value on record."); } } else { if ((StringUtils.isNotBlank(originalPassword) && !validatePass(originalPassword, dbPassword))) { throw new FailedLoginException("Password does not match value on record."); } } } catch (IncorrectResultSizeDataAccessException e) { if (e.getActualSize() == 0) { throw new AccountNotFoundException(username + " not found with SQL query"); } throw new FailedLoginException("Multiple records found for " + username); } catch (DataAccessException e) { throw new PreventedException("SQL exception while executing query for " + username, e); } checkFirstLogin(username); return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null); } @Override protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credential) throws GeneralSecurityException, PreventedException { return authenticateUsernamePasswordInternal(credential, null); } public void setSql(String sql) { this.sql = sql; } public void checkFirstLogin(String username) throws AccountPasswordMustChangeException { String tempsql = "SELECT * FROM MAGBG.ORG_USER WHERE LOGINNAME='%s'"; String querysql = String.format(tempsql, username); List> list = getJdbcTemplate().queryForList(querysql); if (list != null && !list.isEmpty()) { if (m0.equals(list.get(0).get(mIsFirst).toString())) { throw new AccountPasswordMustChangeException(); } } } public boolean isFirstLogin(String username) throws AccountPasswordMustChangeException { String tempsql = "SELECT * FROM MAGBG.ORG_USER WHERE LOGINNAME='%s'"; String querysql = String.format(tempsql, username); List> list = getJdbcTemplate().queryForList(querysql); if (list != null && !list.isEmpty()) { if (m0.equals(list.get(0).get(mIsFirst).toString())) { return true; } } return false; } @Override public void setDataSource(DataSource dataSource) { super.setDataSource(dataSource); } @Override protected JdbcTemplate getJdbcTemplate() { JdbcTemplate jt = super.getJdbcTemplate(); return jt; } public boolean validatePass(String originalPassword, String dbpassword) { return Md5Util.verify(originalPassword, Md5Util.reverse(dbpassword)); } }