mirror of
https://gitee.com/dromara/MaxKey.git
synced 2025-12-06 17:08:29 +08:00
v 1.5.0 RC2
v 1.5.0 RC2
This commit is contained in:
parent
2ac28e572f
commit
27e0c0b376
@ -40,7 +40,7 @@ config.socialsignon.sinaweibo.account.id=id
|
||||
config.socialsignon.sinaweibo.sortorder=1
|
||||
</code></pre>
|
||||
|
||||
配置maxkey/spring/maxkey-support-social.xml
|
||||
配置maxkey/spring/maxkey.xml
|
||||
|
||||
<pre><code class="xml hljs">
|
||||
<bean id="socialSignOnWeibo" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
|
||||
@ -3,9 +3,6 @@ package org.maxkey.authz.cas.endpoint.ticket.service;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.maxkey.authz.cas.endpoint.ticket.Ticket;
|
||||
import org.maxkey.util.SerializationUtils;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
@ -27,9 +24,9 @@ public class JdbcTicketServices extends RandomServiceTicketServices {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public JdbcTicketServices(DataSource dataSource) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
public JdbcTicketServices(JdbcTemplate jdbcTemplate) {
|
||||
Assert.notNull(jdbcTemplate, "jdbcTemplate required");
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -73,7 +73,7 @@ public class FormBasedAuthorizeEndpoint extends AuthorizeBaseEndpoint{
|
||||
modelAndView);
|
||||
}
|
||||
|
||||
|
||||
_logger.debug("FormBased View Name " + modelAndView.getViewName());
|
||||
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ public class FormBasedNetease163EmailAdapter extends AbstractAuthorizeAdapter {
|
||||
|
||||
@Override
|
||||
public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
|
||||
modelAndView.setViewName("authorize/formbased_netease_163email_sso_submint");
|
||||
modelAndView.setViewName("authorize/formbased_163email_sso_submint");
|
||||
AppsFormBasedDetails details=(AppsFormBasedDetails)app;
|
||||
modelAndView.addObject("username", details.getAppUser().getRelatedUsername().substring(details.getAppUser().getRelatedUsername().indexOf("@")));
|
||||
modelAndView.addObject("email", details.getAppUser().getRelatedUsername());
|
||||
|
||||
@ -23,7 +23,7 @@ public class FormBasedNeteaseNoteYoudaoAdapter extends AbstractAuthorizeAdapter
|
||||
|
||||
@Override
|
||||
public ModelAndView authorize(UserInfo userInfo, Object app, String data,ModelAndView modelAndView) {
|
||||
modelAndView.setViewName("authorize/formbased_netease_noteyoudao_sso_submint");
|
||||
modelAndView.setViewName("authorize/formbased_wy_youdao_sso_submint");
|
||||
AppsFormBasedDetails details=(AppsFormBasedDetails)app;
|
||||
modelAndView.addObject("username", details.getAppUser().getRelatedUsername());
|
||||
modelAndView.addObject("password", DigestUtils.md5Hex(details.getAppUser().getRelatedPassword()));
|
||||
|
||||
@ -15,65 +15,70 @@ import org.springframework.jdbc.core.support.SqlLobValue;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of authorization code services that stores the codes and authentication in a database.
|
||||
* Implementation of authorization code services that stores the codes and
|
||||
* authentication in a database.
|
||||
*
|
||||
* @author Crystal.Sea
|
||||
*/
|
||||
public class JdbcAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {
|
||||
|
||||
private static final String DEFAULT_SELECT_STATEMENT = "select code, authentication from oauth_code where code = ?";
|
||||
private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_code (code, authentication) values (?, ?)";
|
||||
private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_code where code = ?";
|
||||
private static final String DEFAULT_SELECT_STATEMENT = "select code, authentication from oauth_code where code = ?";
|
||||
private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_code (code, authentication) values (?, ?)";
|
||||
private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_code where code = ?";
|
||||
|
||||
private String selectAuthenticationSql = DEFAULT_SELECT_STATEMENT;
|
||||
private String insertAuthenticationSql = DEFAULT_INSERT_STATEMENT;
|
||||
private String deleteAuthenticationSql = DEFAULT_DELETE_STATEMENT;
|
||||
private String selectAuthenticationSql = DEFAULT_SELECT_STATEMENT;
|
||||
private String insertAuthenticationSql = DEFAULT_INSERT_STATEMENT;
|
||||
private String deleteAuthenticationSql = DEFAULT_DELETE_STATEMENT;
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public JdbcAuthorizationCodeServices(DataSource dataSource) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
public JdbcAuthorizationCodeServices(DataSource dataSource) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void store(String code, OAuth2Authentication authentication) {
|
||||
jdbcTemplate.update(insertAuthenticationSql,
|
||||
new Object[] { code, new SqlLobValue(SerializationUtils.serialize(authentication)) }, new int[] {
|
||||
Types.VARCHAR, Types.BLOB });
|
||||
}
|
||||
public JdbcAuthorizationCodeServices(JdbcTemplate jdbcTemplate) {
|
||||
Assert.notNull(jdbcTemplate, "jdbcTemplate required");
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void store(String code, OAuth2Authentication authentication) {
|
||||
jdbcTemplate.update(insertAuthenticationSql,
|
||||
new Object[] { code, new SqlLobValue(SerializationUtils.serialize(authentication)) },
|
||||
new int[] { Types.VARCHAR, Types.BLOB });
|
||||
}
|
||||
|
||||
public OAuth2Authentication remove(String code) {
|
||||
OAuth2Authentication authentication;
|
||||
public OAuth2Authentication remove(String code) {
|
||||
OAuth2Authentication authentication;
|
||||
|
||||
try {
|
||||
authentication = jdbcTemplate.queryForObject(selectAuthenticationSql,
|
||||
new RowMapper<OAuth2Authentication>() {
|
||||
public OAuth2Authentication mapRow(ResultSet rs, int rowNum)
|
||||
throws SQLException {
|
||||
return SerializationUtils.deserialize(rs.getBytes("authentication"));
|
||||
}
|
||||
}, code);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
authentication = jdbcTemplate.queryForObject(selectAuthenticationSql,
|
||||
new RowMapper<OAuth2Authentication>() {
|
||||
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return SerializationUtils.deserialize(rs.getBytes("authentication"));
|
||||
}
|
||||
}, code);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (authentication != null) {
|
||||
jdbcTemplate.update(deleteAuthenticationSql, code);
|
||||
}
|
||||
if (authentication != null) {
|
||||
jdbcTemplate.update(deleteAuthenticationSql, code);
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void setSelectAuthenticationSql(String selectAuthenticationSql) {
|
||||
this.selectAuthenticationSql = selectAuthenticationSql;
|
||||
}
|
||||
public void setSelectAuthenticationSql(String selectAuthenticationSql) {
|
||||
this.selectAuthenticationSql = selectAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setInsertAuthenticationSql(String insertAuthenticationSql) {
|
||||
this.insertAuthenticationSql = insertAuthenticationSql;
|
||||
}
|
||||
public void setInsertAuthenticationSql(String insertAuthenticationSql) {
|
||||
this.insertAuthenticationSql = insertAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setDeleteAuthenticationSql(String deleteAuthenticationSql) {
|
||||
this.deleteAuthenticationSql = deleteAuthenticationSql;
|
||||
}
|
||||
public void setDeleteAuthenticationSql(String deleteAuthenticationSql) {
|
||||
this.deleteAuthenticationSql = deleteAuthenticationSql;
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,423 +37,416 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class JdbcTokenStore implements TokenStore {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(JdbcTokenStore.class);
|
||||
private static final Log LOG = LogFactory.getLog(JdbcTokenStore.class);
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT = "insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT = "insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_access_token where token_id = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_access_token where token_id = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_access_token where token_id = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_access_token where token_id = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT = "select token_id, token from oauth_access_token where authentication_id = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT = "select token_id, token from oauth_access_token where authentication_id = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ? and client_id = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT = "select token_id, token from oauth_access_token where user_name = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT = "delete from oauth_access_token where token_id = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT = "select token_id, token from oauth_access_token where client_id = ?";
|
||||
|
||||
private static final String DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT = "delete from oauth_access_token where refresh_token = ?";
|
||||
private static final String DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT = "delete from oauth_access_token where token_id = ?";
|
||||
|
||||
private static final String DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT = "insert into oauth_refresh_token (token_id, token, authentication) values (?, ?, ?)";
|
||||
private static final String DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT = "delete from oauth_access_token where refresh_token = ?";
|
||||
|
||||
private static final String DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_refresh_token where token_id = ?";
|
||||
private static final String DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT = "insert into oauth_refresh_token (token_id, token, authentication) values (?, ?, ?)";
|
||||
|
||||
private static final String DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_refresh_token where token_id = ?";
|
||||
private static final String DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT = "select token_id, token from oauth_refresh_token where token_id = ?";
|
||||
|
||||
private static final String DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT = "delete from oauth_refresh_token where token_id = ?";
|
||||
private static final String DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT = "select token_id, authentication from oauth_refresh_token where token_id = ?";
|
||||
|
||||
private String insertAccessTokenSql = DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT;
|
||||
private static final String DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT = "delete from oauth_refresh_token where token_id = ?";
|
||||
|
||||
private String selectAccessTokenSql = DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT;
|
||||
private String insertAccessTokenSql = DEFAULT_ACCESS_TOKEN_INSERT_STATEMENT;
|
||||
|
||||
private String selectAccessTokenAuthenticationSql = DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
|
||||
private String selectAccessTokenSql = DEFAULT_ACCESS_TOKEN_SELECT_STATEMENT;
|
||||
|
||||
private String selectAccessTokenFromAuthenticationSql = DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT;
|
||||
private String selectAccessTokenAuthenticationSql = DEFAULT_ACCESS_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
|
||||
|
||||
private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT;
|
||||
private String selectAccessTokenFromAuthenticationSql = DEFAULT_ACCESS_TOKEN_FROM_AUTHENTICATION_SELECT_STATEMENT;
|
||||
|
||||
private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT;
|
||||
|
||||
private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT;
|
||||
private String selectAccessTokensFromUserNameAndClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_AND_CLIENT_SELECT_STATEMENT;
|
||||
|
||||
private String deleteAccessTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT;
|
||||
private String selectAccessTokensFromUserNameSql = DEFAULT_ACCESS_TOKENS_FROM_USERNAME_SELECT_STATEMENT;
|
||||
|
||||
private String insertRefreshTokenSql = DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT;
|
||||
private String selectAccessTokensFromClientIdSql = DEFAULT_ACCESS_TOKENS_FROM_CLIENTID_SELECT_STATEMENT;
|
||||
|
||||
private String selectRefreshTokenSql = DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT;
|
||||
private String deleteAccessTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_STATEMENT;
|
||||
|
||||
private String selectRefreshTokenAuthenticationSql = DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
|
||||
private String insertRefreshTokenSql = DEFAULT_REFRESH_TOKEN_INSERT_STATEMENT;
|
||||
|
||||
private String deleteRefreshTokenSql = DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT;
|
||||
private String selectRefreshTokenSql = DEFAULT_REFRESH_TOKEN_SELECT_STATEMENT;
|
||||
|
||||
private String deleteAccessTokenFromRefreshTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT;
|
||||
private String selectRefreshTokenAuthenticationSql = DEFAULT_REFRESH_TOKEN_AUTHENTICATION_SELECT_STATEMENT;
|
||||
|
||||
private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
|
||||
private String deleteRefreshTokenSql = DEFAULT_REFRESH_TOKEN_DELETE_STATEMENT;
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private String deleteAccessTokenFromRefreshTokenSql = DEFAULT_ACCESS_TOKEN_DELETE_FROM_REFRESH_TOKEN_STATEMENT;
|
||||
|
||||
public JdbcTokenStore(DataSource dataSource) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
|
||||
|
||||
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
|
||||
this.authenticationKeyGenerator = authenticationKeyGenerator;
|
||||
}
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
|
||||
OAuth2AccessToken accessToken = null;
|
||||
|
||||
String key = authenticationKeyGenerator.extractKey(authentication);
|
||||
try {
|
||||
accessToken = jdbcTemplate.queryForObject(selectAccessTokenFromAuthenticationSql,
|
||||
new RowMapper<OAuth2AccessToken>() {
|
||||
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAccessToken(rs.getBytes(2));
|
||||
}
|
||||
}, key);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.debug("Failed to find access token for authentication " + authentication);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.error("Could not extract access token for authentication " + authentication, e);
|
||||
}
|
||||
|
||||
if (accessToken != null
|
||||
&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {
|
||||
removeAccessToken(accessToken.getValue());
|
||||
// Keep the store consistent (maybe the same user is represented by this authentication but the details have
|
||||
// changed)
|
||||
storeAccessToken(accessToken, authentication);
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
|
||||
String refreshToken = null;
|
||||
if (token.getRefreshToken() != null) {
|
||||
refreshToken = token.getRefreshToken().getValue();
|
||||
}
|
||||
|
||||
if (readAccessToken(token.getValue())!=null) {
|
||||
removeAccessToken(token.getValue());
|
||||
}
|
||||
|
||||
jdbcTemplate.update(insertAccessTokenSql, new Object[] { extractTokenKey(token.getValue()),
|
||||
new SqlLobValue(serializeAccessToken(token)), authenticationKeyGenerator.extractKey(authentication),
|
||||
authentication.isClientOnly() ? null : authentication.getName(),
|
||||
authentication.getOAuth2Request().getClientId(),
|
||||
new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) }, new int[] {
|
||||
Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB, Types.VARCHAR });
|
||||
}
|
||||
|
||||
public OAuth2AccessToken readAccessToken(String tokenValue) {
|
||||
OAuth2AccessToken accessToken = null;
|
||||
|
||||
try {
|
||||
accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {
|
||||
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAccessToken(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(tokenValue));
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for token " + tokenValue);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize access token for " + tokenValue, e);
|
||||
removeAccessToken(tokenValue);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void removeAccessToken(OAuth2AccessToken token) {
|
||||
removeAccessToken(token.getValue());
|
||||
}
|
||||
|
||||
public void removeAccessToken(String tokenValue) {
|
||||
jdbcTemplate.update(deleteAccessTokenSql, extractTokenKey(tokenValue));
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
|
||||
return readAuthentication(token.getValue());
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthentication(String token) {
|
||||
OAuth2Authentication authentication = null;
|
||||
|
||||
try {
|
||||
authentication = jdbcTemplate.queryForObject(selectAccessTokenAuthenticationSql,
|
||||
new RowMapper<OAuth2Authentication>() {
|
||||
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAuthentication(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(token));
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for token " + token);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize authentication for " + token, e);
|
||||
removeAccessToken(token);
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
|
||||
jdbcTemplate.update(insertRefreshTokenSql, new Object[] { extractTokenKey(refreshToken.getValue()),
|
||||
new SqlLobValue(serializeRefreshToken(refreshToken)),
|
||||
new SqlLobValue(serializeAuthentication(authentication)) }, new int[] { Types.VARCHAR, Types.BLOB,
|
||||
Types.BLOB });
|
||||
}
|
||||
|
||||
public OAuth2RefreshToken readRefreshToken(String token) {
|
||||
OAuth2RefreshToken refreshToken = null;
|
||||
|
||||
try {
|
||||
refreshToken = jdbcTemplate.queryForObject(selectRefreshTokenSql, new RowMapper<OAuth2RefreshToken>() {
|
||||
public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeRefreshToken(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(token));
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find refresh token for token " + token);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize refresh token for token " + token, e);
|
||||
removeRefreshToken(token);
|
||||
}
|
||||
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void removeRefreshToken(OAuth2RefreshToken token) {
|
||||
removeRefreshToken(token.getValue());
|
||||
}
|
||||
|
||||
public void removeRefreshToken(String token) {
|
||||
jdbcTemplate.update(deleteRefreshTokenSql, extractTokenKey(token));
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
|
||||
return readAuthenticationForRefreshToken(token.getValue());
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthenticationForRefreshToken(String value) {
|
||||
OAuth2Authentication authentication = null;
|
||||
|
||||
try {
|
||||
authentication = jdbcTemplate.queryForObject(selectRefreshTokenAuthenticationSql,
|
||||
new RowMapper<OAuth2Authentication>() {
|
||||
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAuthentication(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(value));
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for token " + value);
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize access token for " + value, e);
|
||||
removeRefreshToken(value);
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
|
||||
removeAccessTokenUsingRefreshToken(refreshToken.getValue());
|
||||
}
|
||||
|
||||
public void removeAccessTokenUsingRefreshToken(String refreshToken) {
|
||||
jdbcTemplate.update(deleteAccessTokenFromRefreshTokenSql, new Object[] { extractTokenKey(refreshToken) },
|
||||
new int[] { Types.VARCHAR });
|
||||
}
|
||||
|
||||
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
try {
|
||||
accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(),
|
||||
clientId);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for clientId " + clientId);
|
||||
}
|
||||
}
|
||||
accessTokens = removeNulls(accessTokens);
|
||||
|
||||
return accessTokens;
|
||||
}
|
||||
|
||||
public Collection<OAuth2AccessToken> findTokensByUserName(String userName) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
try {
|
||||
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(),
|
||||
userName);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Failed to find access token for userName " + userName);
|
||||
}
|
||||
accessTokens = removeNulls(accessTokens);
|
||||
|
||||
return accessTokens;
|
||||
}
|
||||
|
||||
public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
try {
|
||||
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameAndClientIdSql, new SafeAccessTokenRowMapper(),
|
||||
userName, clientId);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName);
|
||||
}
|
||||
}
|
||||
accessTokens = removeNulls(accessTokens);
|
||||
|
||||
return accessTokens;
|
||||
}
|
||||
|
||||
private List<OAuth2AccessToken> removeNulls(List<OAuth2AccessToken> accessTokens) {
|
||||
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
|
||||
for (OAuth2AccessToken token : accessTokens) {
|
||||
if (token != null) {
|
||||
tokens.add(token);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
protected String extractTokenKey(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
MessageDigest digest;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] bytes = digest.digest(value.getBytes("UTF-8"));
|
||||
return String.format("%032x", new BigInteger(1, bytes));
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
|
||||
}
|
||||
}
|
||||
|
||||
private final class SafeAccessTokenRowMapper implements RowMapper<OAuth2AccessToken> {
|
||||
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
try {
|
||||
return deserializeAccessToken(rs.getBytes(2));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
String token = rs.getString(1);
|
||||
jdbcTemplate.update(deleteAccessTokenSql, token);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] serializeAccessToken(OAuth2AccessToken token) {
|
||||
return SerializationUtils.serialize(token);
|
||||
}
|
||||
|
||||
protected byte[] serializeRefreshToken(OAuth2RefreshToken token) {
|
||||
return SerializationUtils.serialize(token);
|
||||
}
|
||||
|
||||
protected byte[] serializeAuthentication(OAuth2Authentication authentication) {
|
||||
return SerializationUtils.serialize(authentication);
|
||||
}
|
||||
|
||||
protected OAuth2AccessToken deserializeAccessToken(byte[] token) {
|
||||
return SerializationUtils.deserialize(token);
|
||||
}
|
||||
|
||||
protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) {
|
||||
return SerializationUtils.deserialize(token);
|
||||
}
|
||||
|
||||
protected OAuth2Authentication deserializeAuthentication(byte[] authentication) {
|
||||
return SerializationUtils.deserialize(authentication);
|
||||
}
|
||||
|
||||
public void setInsertAccessTokenSql(String insertAccessTokenSql) {
|
||||
this.insertAccessTokenSql = insertAccessTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokenSql(String selectAccessTokenSql) {
|
||||
this.selectAccessTokenSql = selectAccessTokenSql;
|
||||
}
|
||||
|
||||
public void setDeleteAccessTokenSql(String deleteAccessTokenSql) {
|
||||
this.deleteAccessTokenSql = deleteAccessTokenSql;
|
||||
}
|
||||
|
||||
public void setInsertRefreshTokenSql(String insertRefreshTokenSql) {
|
||||
this.insertRefreshTokenSql = insertRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectRefreshTokenSql(String selectRefreshTokenSql) {
|
||||
this.selectRefreshTokenSql = selectRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setDeleteRefreshTokenSql(String deleteRefreshTokenSql) {
|
||||
this.deleteRefreshTokenSql = deleteRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokenAuthenticationSql(String selectAccessTokenAuthenticationSql) {
|
||||
this.selectAccessTokenAuthenticationSql = selectAccessTokenAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setSelectRefreshTokenAuthenticationSql(String selectRefreshTokenAuthenticationSql) {
|
||||
this.selectRefreshTokenAuthenticationSql = selectRefreshTokenAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokenFromAuthenticationSql(String selectAccessTokenFromAuthenticationSql) {
|
||||
this.selectAccessTokenFromAuthenticationSql = selectAccessTokenFromAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFromRefreshTokenSql) {
|
||||
this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) {
|
||||
this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) {
|
||||
this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) {
|
||||
this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql;
|
||||
}
|
||||
public JdbcTokenStore(DataSource dataSource) {
|
||||
Assert.notNull(dataSource, "DataSource required");
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
public JdbcTokenStore(JdbcTemplate jdbcTemplate) {
|
||||
Assert.notNull(jdbcTemplate, "jdbcTemplate required");
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
|
||||
this.authenticationKeyGenerator = authenticationKeyGenerator;
|
||||
}
|
||||
|
||||
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
|
||||
OAuth2AccessToken accessToken = null;
|
||||
|
||||
String key = authenticationKeyGenerator.extractKey(authentication);
|
||||
try {
|
||||
accessToken = jdbcTemplate.queryForObject(selectAccessTokenFromAuthenticationSql,
|
||||
new RowMapper<OAuth2AccessToken>() {
|
||||
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAccessToken(rs.getBytes(2));
|
||||
}
|
||||
}, key);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.debug("Failed to find access token for authentication " + authentication);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.error("Could not extract access token for authentication " + authentication, e);
|
||||
}
|
||||
|
||||
if (accessToken != null
|
||||
&& !key.equals(authenticationKeyGenerator.extractKey(readAuthentication(accessToken.getValue())))) {
|
||||
removeAccessToken(accessToken.getValue());
|
||||
// Keep the store consistent (maybe the same user is represented by this
|
||||
// authentication but the details have
|
||||
// changed)
|
||||
storeAccessToken(accessToken, authentication);
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
|
||||
String refreshToken = null;
|
||||
if (token.getRefreshToken() != null) {
|
||||
refreshToken = token.getRefreshToken().getValue();
|
||||
}
|
||||
|
||||
if (readAccessToken(token.getValue()) != null) {
|
||||
removeAccessToken(token.getValue());
|
||||
}
|
||||
|
||||
jdbcTemplate.update(insertAccessTokenSql,
|
||||
new Object[] { extractTokenKey(token.getValue()), new SqlLobValue(serializeAccessToken(token)),
|
||||
authenticationKeyGenerator.extractKey(authentication),
|
||||
authentication.isClientOnly() ? null : authentication.getName(),
|
||||
authentication.getOAuth2Request().getClientId(),
|
||||
new SqlLobValue(serializeAuthentication(authentication)), extractTokenKey(refreshToken) },
|
||||
new int[] { Types.VARCHAR, Types.BLOB, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BLOB,
|
||||
Types.VARCHAR });
|
||||
}
|
||||
|
||||
public OAuth2AccessToken readAccessToken(String tokenValue) {
|
||||
OAuth2AccessToken accessToken = null;
|
||||
|
||||
try {
|
||||
accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {
|
||||
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAccessToken(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(tokenValue));
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for token " + tokenValue);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize access token for " + tokenValue, e);
|
||||
removeAccessToken(tokenValue);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void removeAccessToken(OAuth2AccessToken token) {
|
||||
removeAccessToken(token.getValue());
|
||||
}
|
||||
|
||||
public void removeAccessToken(String tokenValue) {
|
||||
jdbcTemplate.update(deleteAccessTokenSql, extractTokenKey(tokenValue));
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
|
||||
return readAuthentication(token.getValue());
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthentication(String token) {
|
||||
OAuth2Authentication authentication = null;
|
||||
|
||||
try {
|
||||
authentication = jdbcTemplate.queryForObject(selectAccessTokenAuthenticationSql,
|
||||
new RowMapper<OAuth2Authentication>() {
|
||||
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAuthentication(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(token));
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for token " + token);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize authentication for " + token, e);
|
||||
removeAccessToken(token);
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
|
||||
jdbcTemplate.update(insertRefreshTokenSql,
|
||||
new Object[] { extractTokenKey(refreshToken.getValue()),
|
||||
new SqlLobValue(serializeRefreshToken(refreshToken)),
|
||||
new SqlLobValue(serializeAuthentication(authentication)) },
|
||||
new int[] { Types.VARCHAR, Types.BLOB, Types.BLOB });
|
||||
}
|
||||
|
||||
public OAuth2RefreshToken readRefreshToken(String token) {
|
||||
OAuth2RefreshToken refreshToken = null;
|
||||
|
||||
try {
|
||||
refreshToken = jdbcTemplate.queryForObject(selectRefreshTokenSql, new RowMapper<OAuth2RefreshToken>() {
|
||||
public OAuth2RefreshToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeRefreshToken(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(token));
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find refresh token for token " + token);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize refresh token for token " + token, e);
|
||||
removeRefreshToken(token);
|
||||
}
|
||||
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void removeRefreshToken(OAuth2RefreshToken token) {
|
||||
removeRefreshToken(token.getValue());
|
||||
}
|
||||
|
||||
public void removeRefreshToken(String token) {
|
||||
jdbcTemplate.update(deleteRefreshTokenSql, extractTokenKey(token));
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
|
||||
return readAuthenticationForRefreshToken(token.getValue());
|
||||
}
|
||||
|
||||
public OAuth2Authentication readAuthenticationForRefreshToken(String value) {
|
||||
OAuth2Authentication authentication = null;
|
||||
|
||||
try {
|
||||
authentication = jdbcTemplate.queryForObject(selectRefreshTokenAuthenticationSql,
|
||||
new RowMapper<OAuth2Authentication>() {
|
||||
public OAuth2Authentication mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
return deserializeAuthentication(rs.getBytes(2));
|
||||
}
|
||||
}, extractTokenKey(value));
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for token " + value);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.warn("Failed to deserialize access token for " + value, e);
|
||||
removeRefreshToken(value);
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
|
||||
removeAccessTokenUsingRefreshToken(refreshToken.getValue());
|
||||
}
|
||||
|
||||
public void removeAccessTokenUsingRefreshToken(String refreshToken) {
|
||||
jdbcTemplate.update(deleteAccessTokenFromRefreshTokenSql, new Object[] { extractTokenKey(refreshToken) },
|
||||
new int[] { Types.VARCHAR });
|
||||
}
|
||||
|
||||
public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
try {
|
||||
accessTokens = jdbcTemplate.query(selectAccessTokensFromClientIdSql, new SafeAccessTokenRowMapper(),
|
||||
clientId);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for clientId " + clientId);
|
||||
}
|
||||
}
|
||||
accessTokens = removeNulls(accessTokens);
|
||||
|
||||
return accessTokens;
|
||||
}
|
||||
|
||||
public Collection<OAuth2AccessToken> findTokensByUserName(String userName) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
try {
|
||||
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameSql, new SafeAccessTokenRowMapper(),
|
||||
userName);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled())
|
||||
LOG.info("Failed to find access token for userName " + userName);
|
||||
}
|
||||
accessTokens = removeNulls(accessTokens);
|
||||
|
||||
return accessTokens;
|
||||
}
|
||||
|
||||
public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String clientId, String userName) {
|
||||
List<OAuth2AccessToken> accessTokens = new ArrayList<OAuth2AccessToken>();
|
||||
|
||||
try {
|
||||
accessTokens = jdbcTemplate.query(selectAccessTokensFromUserNameAndClientIdSql,
|
||||
new SafeAccessTokenRowMapper(), userName, clientId);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("Failed to find access token for clientId " + clientId + " and userName " + userName);
|
||||
}
|
||||
}
|
||||
accessTokens = removeNulls(accessTokens);
|
||||
|
||||
return accessTokens;
|
||||
}
|
||||
|
||||
private List<OAuth2AccessToken> removeNulls(List<OAuth2AccessToken> accessTokens) {
|
||||
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
|
||||
for (OAuth2AccessToken token : accessTokens) {
|
||||
if (token != null) {
|
||||
tokens.add(token);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
protected String extractTokenKey(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
MessageDigest digest;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] bytes = digest.digest(value.getBytes("UTF-8"));
|
||||
return String.format("%032x", new BigInteger(1, bytes));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
|
||||
}
|
||||
}
|
||||
|
||||
private final class SafeAccessTokenRowMapper implements RowMapper<OAuth2AccessToken> {
|
||||
public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
try {
|
||||
return deserializeAccessToken(rs.getBytes(2));
|
||||
} catch (IllegalArgumentException e) {
|
||||
String token = rs.getString(1);
|
||||
jdbcTemplate.update(deleteAccessTokenSql, token);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] serializeAccessToken(OAuth2AccessToken token) {
|
||||
return SerializationUtils.serialize(token);
|
||||
}
|
||||
|
||||
protected byte[] serializeRefreshToken(OAuth2RefreshToken token) {
|
||||
return SerializationUtils.serialize(token);
|
||||
}
|
||||
|
||||
protected byte[] serializeAuthentication(OAuth2Authentication authentication) {
|
||||
return SerializationUtils.serialize(authentication);
|
||||
}
|
||||
|
||||
protected OAuth2AccessToken deserializeAccessToken(byte[] token) {
|
||||
return SerializationUtils.deserialize(token);
|
||||
}
|
||||
|
||||
protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) {
|
||||
return SerializationUtils.deserialize(token);
|
||||
}
|
||||
|
||||
protected OAuth2Authentication deserializeAuthentication(byte[] authentication) {
|
||||
return SerializationUtils.deserialize(authentication);
|
||||
}
|
||||
|
||||
public void setInsertAccessTokenSql(String insertAccessTokenSql) {
|
||||
this.insertAccessTokenSql = insertAccessTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokenSql(String selectAccessTokenSql) {
|
||||
this.selectAccessTokenSql = selectAccessTokenSql;
|
||||
}
|
||||
|
||||
public void setDeleteAccessTokenSql(String deleteAccessTokenSql) {
|
||||
this.deleteAccessTokenSql = deleteAccessTokenSql;
|
||||
}
|
||||
|
||||
public void setInsertRefreshTokenSql(String insertRefreshTokenSql) {
|
||||
this.insertRefreshTokenSql = insertRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectRefreshTokenSql(String selectRefreshTokenSql) {
|
||||
this.selectRefreshTokenSql = selectRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setDeleteRefreshTokenSql(String deleteRefreshTokenSql) {
|
||||
this.deleteRefreshTokenSql = deleteRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokenAuthenticationSql(String selectAccessTokenAuthenticationSql) {
|
||||
this.selectAccessTokenAuthenticationSql = selectAccessTokenAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setSelectRefreshTokenAuthenticationSql(String selectRefreshTokenAuthenticationSql) {
|
||||
this.selectRefreshTokenAuthenticationSql = selectRefreshTokenAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokenFromAuthenticationSql(String selectAccessTokenFromAuthenticationSql) {
|
||||
this.selectAccessTokenFromAuthenticationSql = selectAccessTokenFromAuthenticationSql;
|
||||
}
|
||||
|
||||
public void setDeleteAccessTokenFromRefreshTokenSql(String deleteAccessTokenFromRefreshTokenSql) {
|
||||
this.deleteAccessTokenFromRefreshTokenSql = deleteAccessTokenFromRefreshTokenSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokensFromUserNameSql(String selectAccessTokensFromUserNameSql) {
|
||||
this.selectAccessTokensFromUserNameSql = selectAccessTokensFromUserNameSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokensFromUserNameAndClientIdSql(String selectAccessTokensFromUserNameAndClientIdSql) {
|
||||
this.selectAccessTokensFromUserNameAndClientIdSql = selectAccessTokensFromUserNameAndClientIdSql;
|
||||
}
|
||||
|
||||
public void setSelectAccessTokensFromClientIdSql(String selectAccessTokensFromClientIdSql) {
|
||||
this.selectAccessTokensFromClientIdSql = selectAccessTokensFromClientIdSql;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,8 +49,9 @@ import org.springframework.security.crypto.codec.Base64;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper that translates between JWT encoded token values and OAuth authentication information (in both directions).
|
||||
* Also acts as a {@link TokenEnhancer} when tokens are granted.
|
||||
* Helper that translates between JWT encoded token values and OAuth
|
||||
* authentication information (in both directions). Also acts as a
|
||||
* {@link TokenEnhancer} when tokens are granted.
|
||||
*
|
||||
* @see TokenEnhancer
|
||||
* @see AccessTokenConverter
|
||||
@ -60,219 +61,218 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class JwtAccessTokenConverter implements TokenEnhancer, AccessTokenConverter, InitializingBean {
|
||||
|
||||
/**
|
||||
* Field name for token id.
|
||||
*/
|
||||
public static final String TOKEN_ID = AccessTokenConverter.JTI;
|
||||
/**
|
||||
* Field name for token id.
|
||||
*/
|
||||
public static final String TOKEN_ID = AccessTokenConverter.JTI;
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class);
|
||||
private static final Log logger = LogFactory.getLog(JwtAccessTokenConverter.class);
|
||||
|
||||
private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
|
||||
private AccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
|
||||
|
||||
private JsonParser objectMapper = JsonParserFactory.create();
|
||||
private JsonParser objectMapper = JsonParserFactory.create();
|
||||
|
||||
private String verifierKey = new RandomValueStringGenerator().generate();
|
||||
private String verifierKey = new RandomValueStringGenerator().generate();
|
||||
|
||||
private Signer signer = new MacSigner(verifierKey);
|
||||
private Signer signer = new MacSigner(verifierKey);
|
||||
|
||||
private String signingKey = verifierKey;
|
||||
private String signingKey = verifierKey;
|
||||
|
||||
private SignatureVerifier verifier;
|
||||
private SignatureVerifier verifier;
|
||||
|
||||
/**
|
||||
* @param tokenConverter the tokenConverter to set
|
||||
*/
|
||||
public void setAccessTokenConverter(AccessTokenConverter tokenConverter) {
|
||||
this.tokenConverter = tokenConverter;
|
||||
}
|
||||
/**
|
||||
* @param tokenConverter the tokenConverter to set
|
||||
*/
|
||||
public void setAccessTokenConverter(AccessTokenConverter tokenConverter) {
|
||||
this.tokenConverter = tokenConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tokenConverter in use
|
||||
*/
|
||||
public AccessTokenConverter getAccessTokenConverter() {
|
||||
return tokenConverter;
|
||||
}
|
||||
/**
|
||||
* @return the tokenConverter in use
|
||||
*/
|
||||
public AccessTokenConverter getAccessTokenConverter() {
|
||||
return tokenConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
|
||||
return tokenConverter.convertAccessToken(token, authentication);
|
||||
}
|
||||
@Override
|
||||
public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
|
||||
return tokenConverter.convertAccessToken(token, authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map) {
|
||||
return tokenConverter.extractAccessToken(value, map);
|
||||
}
|
||||
@Override
|
||||
public OAuth2AccessToken extractAccessToken(String value, Map<String, ?> map) {
|
||||
return tokenConverter.extractAccessToken(value, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
|
||||
return tokenConverter.extractAuthentication(map);
|
||||
}
|
||||
@Override
|
||||
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
|
||||
return tokenConverter.extractAuthentication(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the verification key for the token signatures.
|
||||
*
|
||||
* @return the key used to verify tokens
|
||||
*/
|
||||
public Map<String, String> getKey() {
|
||||
Map<String, String> result = new LinkedHashMap<String, String>();
|
||||
result.put("alg", signer.algorithm());
|
||||
result.put("value", verifierKey);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Get the verification key for the token signatures.
|
||||
*
|
||||
* @return the key used to verify tokens
|
||||
*/
|
||||
public Map<String, String> getKey() {
|
||||
Map<String, String> result = new LinkedHashMap<String, String>();
|
||||
result.put("alg", signer.algorithm());
|
||||
result.put("value", verifierKey);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setKeyPair(KeyPair keyPair) {
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA ");
|
||||
signer = new RsaSigner((RSAPrivateKey) privateKey);
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
verifier = new RsaVerifier(publicKey);
|
||||
verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded())) + "\n-----END PUBLIC KEY-----";
|
||||
}
|
||||
/**
|
||||
* Sets the JWT signing key. It can be either a simple MAC key or an RSA key. RSA keys should be in OpenSSH format,
|
||||
* as produced by <tt>ssh-keygen</tt>.
|
||||
*
|
||||
* @param key the key to be used for signing JWTs.
|
||||
*/
|
||||
public void setSigningKey(String key) {
|
||||
Assert.hasText(key);
|
||||
key = key.trim();
|
||||
public void setKeyPair(KeyPair keyPair) {
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
Assert.state(privateKey instanceof RSAPrivateKey, "KeyPair must be an RSA ");
|
||||
signer = new RsaSigner((RSAPrivateKey) privateKey);
|
||||
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
|
||||
verifier = new RsaVerifier(publicKey);
|
||||
verifierKey = "-----BEGIN PUBLIC KEY-----\n" + new String(Base64.encode(publicKey.getEncoded()))
|
||||
+ "\n-----END PUBLIC KEY-----";
|
||||
}
|
||||
|
||||
this.signingKey = key;
|
||||
/**
|
||||
* Sets the JWT signing key. It can be either a simple MAC key or an RSA key.
|
||||
* RSA keys should be in OpenSSH format, as produced by <tt>ssh-keygen</tt>.
|
||||
*
|
||||
* @param key the key to be used for signing JWTs.
|
||||
*/
|
||||
public void setSigningKey(String key) {
|
||||
Assert.hasText(key);
|
||||
key = key.trim();
|
||||
|
||||
if (isPublic(key)) {
|
||||
signer = new RsaSigner(key);
|
||||
logger.info("Configured with RSA signing key");
|
||||
}
|
||||
else {
|
||||
// Assume it's a MAC key
|
||||
this.verifierKey = key;
|
||||
signer = new MacSigner(key);
|
||||
}
|
||||
}
|
||||
this.signingKey = key;
|
||||
|
||||
/**
|
||||
* @return true if the key has a public verifier
|
||||
*/
|
||||
private boolean isPublic(String key) {
|
||||
return key.startsWith("-----BEGIN");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the signing key is a public key
|
||||
*/
|
||||
public boolean isPublic() {
|
||||
return signer instanceof RsaSigner;
|
||||
}
|
||||
if (isPublic(key)) {
|
||||
signer = new RsaSigner(key);
|
||||
logger.info("Configured with RSA signing key");
|
||||
} else {
|
||||
// Assume it's a MAC key
|
||||
this.verifierKey = key;
|
||||
signer = new MacSigner(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The key used for verifying signatures produced by this class. This is not used but is returned from the endpoint
|
||||
* to allow resource servers to obtain the key.
|
||||
*
|
||||
* For an HMAC key it will be the same value as the signing key and does not need to be set. For and RSA key, it
|
||||
* should be set to the String representation of the public key, in a standard format (e.g. OpenSSH keys)
|
||||
*
|
||||
* @param key the signature verification key (typically an RSA public key)
|
||||
*/
|
||||
public void setVerifierKey(String key) {
|
||||
this.verifierKey = key;
|
||||
try {
|
||||
new RsaSigner(verifierKey);
|
||||
throw new IllegalArgumentException("Private key cannot be set as verifierKey property");
|
||||
}
|
||||
catch (Exception expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return true if the key has a public verifier
|
||||
*/
|
||||
private boolean isPublic(String key) {
|
||||
return key.startsWith("-----BEGIN");
|
||||
}
|
||||
|
||||
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
|
||||
String tokenId = result.getValue();
|
||||
if (!info.containsKey(TOKEN_ID)) {
|
||||
info.put(TOKEN_ID, tokenId);
|
||||
}
|
||||
result.setAdditionalInformation(info);
|
||||
result.setValue(encode(result, authentication));
|
||||
OAuth2RefreshToken refreshToken = result.getRefreshToken();
|
||||
if (refreshToken != null) {
|
||||
DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken);
|
||||
encodedRefreshToken.setValue(refreshToken.getValue());
|
||||
Map<String, Object> refreshTokenInfo = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
|
||||
refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue());
|
||||
encodedRefreshToken.setAdditionalInformation(refreshTokenInfo);
|
||||
DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(encode(encodedRefreshToken, authentication));
|
||||
if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
|
||||
Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration();
|
||||
encodedRefreshToken.setExpiration(expiration);
|
||||
token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, authentication), expiration);
|
||||
}
|
||||
result.setRefreshToken(token);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* @return true if the signing key is a public key
|
||||
*/
|
||||
public boolean isPublic() {
|
||||
return signer instanceof RsaSigner;
|
||||
}
|
||||
|
||||
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||
String content;
|
||||
try {
|
||||
content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot convert access token to JSON", e);
|
||||
}
|
||||
String token = JwtHelper.encode(content, signer).getEncoded();
|
||||
return token;
|
||||
}
|
||||
/**
|
||||
* The key used for verifying signatures produced by this class. This is not
|
||||
* used but is returned from the endpoint to allow resource servers to obtain
|
||||
* the key.
|
||||
*
|
||||
* For an HMAC key it will be the same value as the signing key and does not
|
||||
* need to be set. For and RSA key, it should be set to the String
|
||||
* representation of the public key, in a standard format (e.g. OpenSSH keys)
|
||||
*
|
||||
* @param key the signature verification key (typically an RSA public key)
|
||||
*/
|
||||
public void setVerifierKey(String key) {
|
||||
this.verifierKey = key;
|
||||
try {
|
||||
new RsaSigner(verifierKey);
|
||||
throw new IllegalArgumentException("Private key cannot be set as verifierKey property");
|
||||
} catch (Exception expected) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, Object> decode(String token) {
|
||||
try {
|
||||
Jwt jwt = JwtHelper.decodeAndVerify(token, verifier);
|
||||
String content = jwt.getClaims();
|
||||
Map<String, Object> map = objectMapper.parseMap(content);
|
||||
if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
|
||||
Integer intValue = (Integer) map.get(EXP);
|
||||
map.put(EXP, new Long(intValue));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new InvalidTokenException("Cannot convert access token to JSON", e);
|
||||
}
|
||||
}
|
||||
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||
DefaultOAuth2AccessToken result = new DefaultOAuth2AccessToken(accessToken);
|
||||
Map<String, Object> info = new LinkedHashMap<String, Object>(accessToken.getAdditionalInformation());
|
||||
String tokenId = result.getValue();
|
||||
if (!info.containsKey(TOKEN_ID)) {
|
||||
info.put(TOKEN_ID, tokenId);
|
||||
}
|
||||
result.setAdditionalInformation(info);
|
||||
result.setValue(encode(result, authentication));
|
||||
OAuth2RefreshToken refreshToken = result.getRefreshToken();
|
||||
if (refreshToken != null) {
|
||||
DefaultOAuth2AccessToken encodedRefreshToken = new DefaultOAuth2AccessToken(accessToken);
|
||||
encodedRefreshToken.setValue(refreshToken.getValue());
|
||||
Map<String, Object> refreshTokenInfo = new LinkedHashMap<String, Object>(
|
||||
accessToken.getAdditionalInformation());
|
||||
refreshTokenInfo.put(TOKEN_ID, encodedRefreshToken.getValue());
|
||||
encodedRefreshToken.setAdditionalInformation(refreshTokenInfo);
|
||||
DefaultOAuth2RefreshToken token = new DefaultOAuth2RefreshToken(
|
||||
encode(encodedRefreshToken, authentication));
|
||||
if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
|
||||
Date expiration = ((ExpiringOAuth2RefreshToken) refreshToken).getExpiration();
|
||||
encodedRefreshToken.setExpiration(expiration);
|
||||
token = new DefaultExpiringOAuth2RefreshToken(encode(encodedRefreshToken, authentication), expiration);
|
||||
}
|
||||
result.setRefreshToken(token);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// Check the signing and verification keys match
|
||||
if (signer instanceof RsaSigner) {
|
||||
RsaVerifier verifier;
|
||||
try {
|
||||
verifier = new RsaVerifier(verifierKey);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Unable to create an RSA verifier from verifierKey");
|
||||
return;
|
||||
}
|
||||
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
|
||||
String content;
|
||||
try {
|
||||
content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot convert access token to JSON", e);
|
||||
}
|
||||
String token = JwtHelper.encode(content, signer).getEncoded();
|
||||
return token;
|
||||
}
|
||||
|
||||
byte[] test = "test".getBytes();
|
||||
try {
|
||||
verifier.verify(test, signer.sign(test));
|
||||
logger.info("Signing and verification RSA keys match");
|
||||
}
|
||||
catch (InvalidSignatureException e) {
|
||||
logger.error("Signing and verification RSA keys do not match");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Avoid a race condition where setters are called in the wrong order. Use of == is intentional.
|
||||
Assert.state(this.signingKey == this.verifierKey,
|
||||
"For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key");
|
||||
}
|
||||
SignatureVerifier verifier = new MacSigner(verifierKey);
|
||||
try {
|
||||
verifier = new RsaVerifier(verifierKey);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Unable to create an RSA verifier from verifierKey");
|
||||
}
|
||||
this.verifier = verifier;
|
||||
}
|
||||
protected Map<String, Object> decode(String token) {
|
||||
try {
|
||||
Jwt jwt = JwtHelper.decodeAndVerify(token, verifier);
|
||||
String content = jwt.getClaims();
|
||||
Map<String, Object> map = objectMapper.parseMap(content);
|
||||
if (map.containsKey(EXP) && map.get(EXP) instanceof Integer) {
|
||||
Integer intValue = (Integer) map.get(EXP);
|
||||
map.put(EXP, new Long(intValue));
|
||||
}
|
||||
return map;
|
||||
} catch (Exception e) {
|
||||
throw new InvalidTokenException("Cannot convert access token to JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// Check the signing and verification keys match
|
||||
if (signer instanceof RsaSigner) {
|
||||
RsaVerifier verifier;
|
||||
try {
|
||||
verifier = new RsaVerifier(verifierKey);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to create an RSA verifier from verifierKey");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] test = "test".getBytes();
|
||||
try {
|
||||
verifier.verify(test, signer.sign(test));
|
||||
logger.info("Signing and verification RSA keys match");
|
||||
} catch (InvalidSignatureException e) {
|
||||
logger.error("Signing and verification RSA keys do not match");
|
||||
}
|
||||
} else {
|
||||
// Avoid a race condition where setters are called in the wrong order. Use of ==
|
||||
// is intentional.
|
||||
Assert.state(this.signingKey == this.verifierKey,
|
||||
"For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key");
|
||||
}
|
||||
SignatureVerifier verifier = new MacSigner(verifierKey);
|
||||
try {
|
||||
verifier = new RsaVerifier(verifierKey);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to create an RSA verifier from verifierKey");
|
||||
}
|
||||
this.verifier = verifier;
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,14 @@ import org.springframework.context.annotation.PropertySource;
|
||||
"org.maxkey.domain.userinfo",
|
||||
"org.maxkey.api.v1.contorller",
|
||||
"org.maxkey.web.endpoint",
|
||||
"org.maxkey.web.contorller"
|
||||
"org.maxkey.web.contorller",
|
||||
//single sign on protocol
|
||||
"org.maxkey.authz.endpoint",
|
||||
"org.maxkey.authz.desktop.endpoint",
|
||||
"org.maxkey.authz.exapi.endpoint",
|
||||
"org.maxkey.authz.formbased.endpoint",
|
||||
"org.maxkey.authz.ltpa.endpoint",
|
||||
"org.maxkey.authz.token.endpoint",
|
||||
})
|
||||
public class MaxKeyConfig implements InitializingBean {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(MaxKeyConfig.class);
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
package org.maxkey.autoconfigure;
|
||||
|
||||
import org.maxkey.authz.cas.endpoint.ticket.service.InMemoryTicketServices;
|
||||
import org.maxkey.authz.cas.endpoint.ticket.service.JdbcTicketServices;
|
||||
import org.maxkey.authz.cas.endpoint.ticket.service.RedisTicketServices;
|
||||
import org.maxkey.authz.cas.endpoint.ticket.service.TicketServices;
|
||||
import org.maxkey.persistence.redis.RedisConnectionFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = {
|
||||
"org.maxkey.authz.cas.endpoint"
|
||||
})
|
||||
@PropertySource("classpath:/application.properties")
|
||||
public class CasAutoConfiguration implements InitializingBean {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(CasAutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* TicketServices.
|
||||
* @param persistence int
|
||||
* @param validity int
|
||||
* @return casTicketServices
|
||||
*/
|
||||
@Bean(name = "casTicketServices")
|
||||
public TicketServices casTicketServices(
|
||||
@Value("${config.server.persistence}") int persistence,
|
||||
@Value("${config.login.remeberme.validity}") int validity,
|
||||
JdbcTemplate jdbcTemplate,
|
||||
RedisConnectionFactory jedisConnectionFactory) {
|
||||
TicketServices casTicketServices = null;
|
||||
if (persistence == 0) {
|
||||
casTicketServices = new InMemoryTicketServices();
|
||||
_logger.debug("InMemoryTicketServices");
|
||||
} else if (persistence == 1) {
|
||||
casTicketServices = new JdbcTicketServices(jdbcTemplate);
|
||||
_logger.debug("JdbcTicketServices");
|
||||
} else if (persistence == 2) {
|
||||
casTicketServices = new RedisTicketServices(jedisConnectionFactory);
|
||||
_logger.debug("RedisTicketServices");
|
||||
}
|
||||
return casTicketServices;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,334 @@
|
||||
package org.maxkey.autoconfigure;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.maxkey.authn.support.jwt.JwtLoginService;
|
||||
import org.maxkey.authz.oauth2.provider.ClientDetailsService;
|
||||
import org.maxkey.authz.oauth2.provider.approval.TokenApprovalStore;
|
||||
import org.maxkey.authz.oauth2.provider.approval.controller.OAuth20UserApprovalHandler;
|
||||
import org.maxkey.authz.oauth2.provider.client.ClientDetailsUserDetailsService;
|
||||
import org.maxkey.authz.oauth2.provider.client.JdbcClientDetailsService;
|
||||
import org.maxkey.authz.oauth2.provider.code.AuthorizationCodeServices;
|
||||
import org.maxkey.authz.oauth2.provider.code.InMemoryAuthorizationCodeServices;
|
||||
import org.maxkey.authz.oauth2.provider.code.JdbcAuthorizationCodeServices;
|
||||
import org.maxkey.authz.oauth2.provider.code.RedisAuthorizationCodeServices;
|
||||
import org.maxkey.authz.oauth2.provider.request.DefaultOAuth2RequestFactory;
|
||||
import org.maxkey.authz.oauth2.provider.token.TokenStore;
|
||||
import org.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
|
||||
import org.maxkey.authz.oauth2.provider.token.store.InMemoryTokenStore;
|
||||
import org.maxkey.authz.oauth2.provider.token.store.JdbcTokenStore;
|
||||
import org.maxkey.authz.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
import org.maxkey.authz.oauth2.provider.token.store.RedisTokenStore;
|
||||
import org.maxkey.authz.oidc.idtoken.OIDCIdTokenEnhancer;
|
||||
import org.maxkey.config.oidc.OIDCProviderMetadataDetails;
|
||||
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
|
||||
import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
|
||||
import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
|
||||
import org.maxkey.persistence.redis.RedisConnectionFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import com.nimbusds.jose.JOSEException;
|
||||
import com.nimbusds.jose.JWEAlgorithm;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = {
|
||||
"org.maxkey.authz.oauth2.provider.endpoint",
|
||||
"org.maxkey.authz.oauth2.provider.userinfo.endpoint",
|
||||
"org.maxkey.authz.oauth2.provider.approval.controller"
|
||||
})
|
||||
@PropertySource("classpath:/application.properties")
|
||||
@PropertySource("classpath:/config/applicationConfig.properties")
|
||||
public class Oauth20AutoConfiguration implements InitializingBean {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(Oauth20AutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* OIDCProviderMetadataDetails.
|
||||
* Self-issued Provider Metadata
|
||||
* http://openid.net/specs/openid-connect-core-1_0.html#SelfIssued
|
||||
*/
|
||||
@Bean(name = "oidcProviderMetadata")
|
||||
public OIDCProviderMetadataDetails OIDCProviderMetadataDetails(
|
||||
@Value("${config.oidc.metadata.issuer}")
|
||||
String issuer,
|
||||
@Value("${config.oidc.metadata.authorizationEndpoint}")
|
||||
URI authorizationEndpoint,
|
||||
@Value("${config.oidc.metadata.tokenEndpoint}")
|
||||
URI tokenEndpoint,
|
||||
@Value("${config.oidc.metadata.userinfoEndpoint}")
|
||||
URI userinfoEndpoint) {
|
||||
_logger.debug("RedisConnectionFactory init .");
|
||||
OIDCProviderMetadataDetails oidcProviderMetadata = new OIDCProviderMetadataDetails();
|
||||
oidcProviderMetadata.setIssuer(issuer);
|
||||
oidcProviderMetadata.setAuthorizationEndpoint(authorizationEndpoint);
|
||||
oidcProviderMetadata.setTokenEndpoint(tokenEndpoint);
|
||||
oidcProviderMetadata.setUserinfoEndpoint(userinfoEndpoint);
|
||||
return oidcProviderMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* jwtSetKeyStore.
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = "jwkSetKeyStore")
|
||||
public JWKSetKeyStore jwtSetKeyStore() {
|
||||
JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore();
|
||||
ClassPathResource classPathResource = new ClassPathResource("/config/keystore.jwks");
|
||||
jwkSetKeyStore.setLocation(classPathResource);
|
||||
return jwkSetKeyStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* jwtSetKeyStore.
|
||||
* @return
|
||||
* @throws JOSEException
|
||||
* @throws InvalidKeySpecException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
@Bean(name = "jwtSignerValidationService")
|
||||
public DefaultJwtSigningAndValidationService jwtSignerValidationService(
|
||||
JWKSetKeyStore jwtSetKeyStore)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
|
||||
DefaultJwtSigningAndValidationService jwtSignerValidationService =
|
||||
new DefaultJwtSigningAndValidationService(jwtSetKeyStore);
|
||||
jwtSignerValidationService.setDefaultSignerKeyId("maxkey_rsa");
|
||||
jwtSignerValidationService.setDefaultSigningAlgorithmName("RS256");
|
||||
return jwtSignerValidationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* jwtSetKeyStore.
|
||||
* @return
|
||||
* @throws JOSEException
|
||||
* @throws InvalidKeySpecException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
@Bean(name = "jwtEncryptionService")
|
||||
public DefaultJwtEncryptionAndDecryptionService jwtEncryptionService(
|
||||
JWKSetKeyStore jwtSetKeyStore)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
|
||||
DefaultJwtEncryptionAndDecryptionService jwtEncryptionService =
|
||||
new DefaultJwtEncryptionAndDecryptionService(jwtSetKeyStore);
|
||||
jwtEncryptionService.setDefaultAlgorithm(JWEAlgorithm.RSA1_5);//RSA1_5
|
||||
jwtEncryptionService.setDefaultDecryptionKeyId("maxkey_rsa");
|
||||
jwtEncryptionService.setDefaultEncryptionKeyId("maxkey_rsa");
|
||||
return jwtEncryptionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* JwtLoginService.
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = "jwtLoginService")
|
||||
public JwtLoginService jwtLoginService(
|
||||
DefaultJwtSigningAndValidationService jwtSignerValidationService,
|
||||
OIDCProviderMetadataDetails oidcProviderMetadata) {
|
||||
JwtLoginService jwkSetKeyStore = new JwtLoginService();
|
||||
jwkSetKeyStore.setJwtSignerValidationService(jwtSignerValidationService);
|
||||
jwkSetKeyStore.setJwtProviderMetadata(oidcProviderMetadata);
|
||||
return jwkSetKeyStore;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* tokenEnhancer.
|
||||
* @return
|
||||
*/
|
||||
@Bean(name = "tokenEnhancer")
|
||||
public OIDCIdTokenEnhancer tokenEnhancer(
|
||||
DefaultJwtSigningAndValidationService jwtSignerValidationService,
|
||||
DefaultJwtEncryptionAndDecryptionService jwtEncryptionService,
|
||||
OIDCProviderMetadataDetails oidcProviderMetadata,
|
||||
ClientDetailsService oauth20JdbcClientDetailsService) {
|
||||
OIDCIdTokenEnhancer tokenEnhancer = new OIDCIdTokenEnhancer();
|
||||
tokenEnhancer.setJwtSignerService(jwtSignerValidationService);
|
||||
tokenEnhancer.setJwtEnDecryptionService(jwtEncryptionService);
|
||||
tokenEnhancer.setClientDetailsService(oauth20JdbcClientDetailsService);
|
||||
tokenEnhancer.setProviderMetadata(oidcProviderMetadata);
|
||||
return tokenEnhancer;
|
||||
}
|
||||
//以上部分为了支持OpenID Connect 1.0
|
||||
|
||||
|
||||
/**
|
||||
* AuthorizationCodeServices.
|
||||
* @param persistence int
|
||||
* @return oauth20AuthorizationCodeServices
|
||||
*/
|
||||
@Bean(name = "oauth20AuthorizationCodeServices")
|
||||
public AuthorizationCodeServices oauth20AuthorizationCodeServices(
|
||||
@Value("${config.server.persistence}") int persistence,
|
||||
JdbcTemplate jdbcTemplate,
|
||||
RedisConnectionFactory jedisConnectionFactory) {
|
||||
AuthorizationCodeServices authorizationCodeServices = null;
|
||||
if (persistence == 0) {
|
||||
authorizationCodeServices = new InMemoryAuthorizationCodeServices();
|
||||
_logger.debug("InMemoryAuthorizationCodeServices");
|
||||
} else if (persistence == 1) {
|
||||
authorizationCodeServices = new JdbcAuthorizationCodeServices(jdbcTemplate);
|
||||
_logger.debug("JdbcAuthorizationCodeServices");
|
||||
} else if (persistence == 2) {
|
||||
authorizationCodeServices = new RedisAuthorizationCodeServices(jedisConnectionFactory);
|
||||
_logger.debug("RedisAuthorizationCodeServices");
|
||||
}
|
||||
return authorizationCodeServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* TokenStore.
|
||||
* @param persistence int
|
||||
* @return oauth20TokenStore
|
||||
*/
|
||||
@Bean(name = "oauth20TokenStore")
|
||||
public TokenStore oauth20TokenStore(
|
||||
@Value("${config.server.persistence}") int persistence,
|
||||
JdbcTemplate jdbcTemplate,
|
||||
RedisConnectionFactory jedisConnectionFactory) {
|
||||
TokenStore tokenStore = null;
|
||||
if (persistence == 0) {
|
||||
tokenStore = new InMemoryTokenStore();
|
||||
_logger.debug("InMemoryTokenStore");
|
||||
} else if (persistence == 1) {
|
||||
tokenStore = new JdbcTokenStore(jdbcTemplate);
|
||||
_logger.debug("JdbcTokenStore");
|
||||
} else if (persistence == 2) {
|
||||
tokenStore = new RedisTokenStore(jedisConnectionFactory);
|
||||
_logger.debug("RedisTokenStore");
|
||||
}
|
||||
return tokenStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* jwtAccessTokenConverter.
|
||||
* @return converter
|
||||
*/
|
||||
@Bean(name = "converter")
|
||||
public JwtAccessTokenConverter jwtAccessTokenConverter() {
|
||||
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
|
||||
return jwtAccessTokenConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* clientDetailsService.
|
||||
* @return oauth20JdbcClientDetailsService
|
||||
*/
|
||||
@Bean(name = "oauth20JdbcClientDetailsService")
|
||||
public JdbcClientDetailsService clientDetailsService(DataSource dataSource,PasswordEncoder passwordReciprocal) {
|
||||
JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
|
||||
clientDetailsService.setPasswordEncoder(passwordReciprocal);
|
||||
return clientDetailsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* clientDetailsUserDetailsService.
|
||||
* @return oauth20ClientDetailsUserService
|
||||
*/
|
||||
@Bean(name = "oauth20ClientDetailsUserService")
|
||||
public ClientDetailsUserDetailsService clientDetailsUserDetailsService(
|
||||
JdbcClientDetailsService oauth20JdbcClientDetailsService,PasswordEncoder passwordReciprocal) {
|
||||
ClientDetailsUserDetailsService cientDetailsUserDetailsService =
|
||||
new ClientDetailsUserDetailsService(oauth20JdbcClientDetailsService);
|
||||
cientDetailsUserDetailsService.setPasswordEncoder(passwordReciprocal);
|
||||
return cientDetailsUserDetailsService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* clientDetailsUserDetailsService.
|
||||
* @return oauth20TokenServices
|
||||
*/
|
||||
@Bean(name = "oauth20TokenServices")
|
||||
public DefaultTokenServices DefaultTokenServices(
|
||||
JdbcClientDetailsService oauth20JdbcClientDetailsService,
|
||||
TokenStore oauth20TokenStore,
|
||||
OIDCIdTokenEnhancer tokenEnhancer) {
|
||||
DefaultTokenServices tokenServices = new DefaultTokenServices();
|
||||
tokenServices.setClientDetailsService(oauth20JdbcClientDetailsService);
|
||||
tokenServices.setTokenEnhancer(tokenEnhancer);
|
||||
tokenServices.setTokenStore(oauth20TokenStore);
|
||||
tokenServices.setSupportRefreshToken(true);
|
||||
return tokenServices;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TokenApprovalStore.
|
||||
* @return oauth20ApprovalStore
|
||||
*/
|
||||
@Bean(name = "oauth20ApprovalStore")
|
||||
public TokenApprovalStore tokenApprovalStore(
|
||||
TokenStore oauth20TokenStore) {
|
||||
TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
|
||||
tokenApprovalStore.setTokenStore(oauth20TokenStore);
|
||||
return tokenApprovalStore;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* OAuth2RequestFactory.
|
||||
* @return oAuth2RequestFactory
|
||||
*/
|
||||
@Bean(name = "oAuth2RequestFactory")
|
||||
public DefaultOAuth2RequestFactory oauth2RequestFactory(
|
||||
JdbcClientDetailsService oauth20JdbcClientDetailsService) {
|
||||
DefaultOAuth2RequestFactory oauth2RequestFactory =
|
||||
new DefaultOAuth2RequestFactory(oauth20JdbcClientDetailsService);
|
||||
return oauth2RequestFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth20UserApprovalHandler.
|
||||
* @return oauth20UserApprovalHandler
|
||||
*/
|
||||
@Bean(name = "oauth20UserApprovalHandler")
|
||||
public OAuth20UserApprovalHandler oauth20UserApprovalHandler(
|
||||
JdbcClientDetailsService oauth20JdbcClientDetailsService,
|
||||
DefaultOAuth2RequestFactory oAuth2RequestFactory,
|
||||
TokenApprovalStore oauth20ApprovalStore
|
||||
) {
|
||||
OAuth20UserApprovalHandler userApprovalHandler = new OAuth20UserApprovalHandler();
|
||||
userApprovalHandler.setApprovalStore(oauth20ApprovalStore);
|
||||
userApprovalHandler.setRequestFactory(oAuth2RequestFactory);
|
||||
userApprovalHandler.setClientDetailsService(oauth20JdbcClientDetailsService);
|
||||
return userApprovalHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* ProviderManager.
|
||||
* @return oauth20ClientAuthenticationManager
|
||||
*/
|
||||
@Bean(name = "oauth20ClientAuthenticationManager")
|
||||
public ProviderManager oauth20ClientAuthenticationManager(
|
||||
ClientDetailsUserDetailsService oauth20ClientDetailsUserService
|
||||
) {
|
||||
DaoAuthenticationProvider daoAuthenticationProvider= new DaoAuthenticationProvider();
|
||||
PasswordEncoder passwordEncoder = NoOpPasswordEncoder.getInstance();
|
||||
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
|
||||
daoAuthenticationProvider.setUserDetailsService(oauth20ClientDetailsUserService);
|
||||
ProviderManager clientAuthenticationManager = new ProviderManager(daoAuthenticationProvider);
|
||||
return clientAuthenticationManager;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,322 @@
|
||||
package org.maxkey.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.exception.VelocityException;
|
||||
import org.maxkey.authz.saml.common.EndpointGenerator;
|
||||
import org.maxkey.authz.saml.service.IDService;
|
||||
import org.maxkey.authz.saml.service.TimeService;
|
||||
import org.maxkey.authz.saml20.binding.decoder.OpenHTTPPostDecoder;
|
||||
import org.maxkey.authz.saml20.binding.decoder.OpenHTTPPostSimpleSignDecoder;
|
||||
import org.maxkey.authz.saml20.binding.decoder.OpenHTTPRedirectDecoder;
|
||||
import org.maxkey.authz.saml20.binding.impl.ExtractPostBindingAdapter;
|
||||
import org.maxkey.authz.saml20.binding.impl.ExtractRedirectBindingAdapter;
|
||||
import org.maxkey.authz.saml20.binding.impl.PostBindingAdapter;
|
||||
import org.maxkey.authz.saml20.binding.impl.PostSimpleSignBindingAdapter;
|
||||
import org.maxkey.authz.saml20.provider.xml.AuthnResponseGenerator;
|
||||
import org.maxkey.authz.saml20.xml.SAML2ValidatorSuite;
|
||||
import org.maxkey.crypto.keystore.KeyStoreLoader;
|
||||
import org.maxkey.domain.Saml20Metadata;
|
||||
import org.opensaml.common.binding.security.IssueInstantRule;
|
||||
import org.opensaml.common.binding.security.MessageReplayRule;
|
||||
import org.opensaml.util.storage.MapBasedStorageService;
|
||||
import org.opensaml.util.storage.ReplayCache;
|
||||
import org.opensaml.xml.ConfigurationException;
|
||||
import org.opensaml.xml.parse.BasicParserPool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.ui.velocity.VelocityEngineFactoryBean;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = {
|
||||
"org.maxkey.authz.saml20.provider.endpoint",
|
||||
"org.maxkey.authz.saml20.metadata.endpoint",
|
||||
})
|
||||
@PropertySource("classpath:/application.properties")
|
||||
@PropertySource("classpath:/config/applicationConfig.properties")
|
||||
public class Saml20AutoConfiguration implements InitializingBean {
|
||||
private static final Logger _logger = LoggerFactory.getLogger(Saml20AutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* samlBootstrapInitializer.
|
||||
* @return samlBootstrapInitializer
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
@Bean(name = "samlBootstrapInitializer")
|
||||
public String samlBootstrapInitializer() throws ConfigurationException {
|
||||
org.opensaml.DefaultBootstrap.bootstrap();
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* TimeService.
|
||||
* @return timeService
|
||||
*/
|
||||
@Bean(name = "timeService")
|
||||
public TimeService TimeService() {
|
||||
TimeService timeService = new TimeService();
|
||||
return timeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* IDService.
|
||||
* @return idService
|
||||
*/
|
||||
@Bean(name = "idService")
|
||||
public IDService idService() {
|
||||
IDService idService = new IDService();
|
||||
return idService;
|
||||
}
|
||||
|
||||
/**
|
||||
* EndpointGenerator.
|
||||
* @return endpointGenerator
|
||||
*/
|
||||
@Bean(name = "endpointGenerator")
|
||||
public EndpointGenerator endpointGenerator() {
|
||||
EndpointGenerator generator = new EndpointGenerator();
|
||||
return generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* AuthnResponseGenerator.
|
||||
* @return authnResponseGenerator
|
||||
*/
|
||||
@Bean(name = "authnResponseGenerator")
|
||||
public AuthnResponseGenerator authnResponseGenerator(TimeService timeService,IDService idService,
|
||||
@Value("${config.saml.v20.idp.issuer}") String issuerEntityName) {
|
||||
AuthnResponseGenerator generator = new AuthnResponseGenerator(issuerEntityName,timeService,idService);
|
||||
return generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* IssuerEntityName.
|
||||
* @return issuerEntityName
|
||||
*/
|
||||
@Bean(name = "issuerEntityName")
|
||||
public String issuerEntityName(
|
||||
@Value("${config.saml.v20.idp.issuer}") String issuerEntityName) {
|
||||
return issuerEntityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saml20Metadata.
|
||||
* @return saml20Metadata
|
||||
*/
|
||||
@Bean(name = "saml20Metadata")
|
||||
public Saml20Metadata saml20Metadata(
|
||||
@Value("${config.saml.v20.metadata.orgName}") String orgName,
|
||||
@Value("${config.saml.v20.metadata.orgDisplayName}") String orgDisplayName,
|
||||
@Value("${config.saml.v20.metadata.orgURL}") String orgURL,
|
||||
@Value("${config.saml.v20.metadata.company}") String company,
|
||||
@Value("${config.saml.v20.metadata.contactType}") String contactType,
|
||||
@Value("${config.saml.v20.metadata.givenName}") String givenName,
|
||||
@Value("${config.saml.v20.metadata.surName}") String surName,
|
||||
@Value("${config.saml.v20.metadata.emailAddress}") String emailAddress,
|
||||
@Value("${config.saml.v20.metadata.telephoneNumber}") String telephoneNumber) {
|
||||
Saml20Metadata metadata = new Saml20Metadata();
|
||||
metadata.setOrgName(orgName);
|
||||
metadata.setOrgDisplayName(orgDisplayName);
|
||||
metadata.setOrgURL(orgURL);
|
||||
metadata.setCompany(company);
|
||||
metadata.setContactType(contactType);
|
||||
metadata.setGivenName(givenName);
|
||||
metadata.setSurName(surName);
|
||||
metadata.setEmailAddress(emailAddress);
|
||||
metadata.setTelephoneNumber(telephoneNumber);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* SAML2ValidatorSuite.
|
||||
* @return samlValidaotrSuite
|
||||
*/
|
||||
@Bean(name = "samlValidaotrSuite")
|
||||
public SAML2ValidatorSuite validatorSuite() {
|
||||
SAML2ValidatorSuite validatorSuite = new SAML2ValidatorSuite();
|
||||
return validatorSuite;
|
||||
}
|
||||
|
||||
/**
|
||||
* MapBasedStorageService.
|
||||
* @return mapBasedStorageService
|
||||
*/
|
||||
@Bean(name = "mapBasedStorageService")
|
||||
public MapBasedStorageService mapBasedStorageService() {
|
||||
MapBasedStorageService mapBasedStorageService = new MapBasedStorageService();
|
||||
return mapBasedStorageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* VelocityEngineFactoryBean.
|
||||
* @return velocityEngine
|
||||
* @throws IOException
|
||||
* @throws VelocityException
|
||||
*/
|
||||
@Bean(name = "velocityEngine")
|
||||
public VelocityEngine velocityEngine() throws VelocityException, IOException {
|
||||
VelocityEngineFactoryBean factory = new VelocityEngineFactoryBean();
|
||||
factory.setPreferFileSystemAccess(false);
|
||||
Properties velocityProperties = new Properties();
|
||||
velocityProperties.put("resource.loader", "classpath");
|
||||
velocityProperties.put("classpath.resource.loader.class",
|
||||
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
|
||||
factory.setVelocityProperties(velocityProperties);
|
||||
return factory.createVelocityEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* ReplayCache.
|
||||
* @return replayCache
|
||||
*/
|
||||
@Bean(name = "replayCache")
|
||||
public ReplayCache replayCache(MapBasedStorageService mapBasedStorageService,
|
||||
@Value("${config.saml.v20.replay.cache.life.in.millis}") long duration) {
|
||||
ReplayCache replayCache = new ReplayCache(mapBasedStorageService,duration);
|
||||
return replayCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* MessageReplayRule.
|
||||
* @return messageReplayRule
|
||||
*/
|
||||
@Bean(name = "messageReplayRule")
|
||||
public MessageReplayRule messageReplayRule(ReplayCache replayCache) {
|
||||
MessageReplayRule messageReplayRule = new MessageReplayRule(replayCache);
|
||||
return messageReplayRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* BasicParserPool.
|
||||
* @return samlParserPool
|
||||
*/
|
||||
@Bean(name = "samlParserPool")
|
||||
public BasicParserPool samlParserPool(
|
||||
@Value("${config.saml.v20.max.parser.pool.size}") int maxPoolSize) {
|
||||
BasicParserPool samlParserPool = new BasicParserPool();
|
||||
samlParserPool.setMaxPoolSize(maxPoolSize);
|
||||
return samlParserPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* IssueInstantRule.
|
||||
* @return issueInstantRule
|
||||
*/
|
||||
@Bean(name = "issueInstantRule")
|
||||
public IssueInstantRule issueInstantRule(
|
||||
@Value("${config.saml.v20.issue.instant.check.clock.skew.in.seconds}") int newClockSkew,
|
||||
@Value("${config.saml.v20.issue.instant.check.validity.time.in.seconds}") int newExpires) {
|
||||
IssueInstantRule decoder = new IssueInstantRule(newClockSkew,newExpires);
|
||||
decoder.setRequiredRule(true);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenHTTPPostSimpleSignDecoder.
|
||||
* @return openHTTPPostSimpleSignDecoder
|
||||
*/
|
||||
@Bean(name = "openHTTPPostSimpleSignDecoder")
|
||||
public OpenHTTPPostSimpleSignDecoder openHTTPPostSimpleSignDecoder(BasicParserPool samlParserPool,
|
||||
@Value("${config.saml.v20.idp.receiver.endpoint}") String receiverEndpoint) {
|
||||
OpenHTTPPostSimpleSignDecoder decoder = new OpenHTTPPostSimpleSignDecoder(samlParserPool);
|
||||
decoder.setReceiverEndpoint(receiverEndpoint);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenHTTPPostDecoder.
|
||||
* @return openHTTPPostDecoder
|
||||
*/
|
||||
@Bean(name = "openHTTPPostDecoder")
|
||||
public OpenHTTPPostDecoder openHTTPPostDecoder(BasicParserPool samlParserPool,
|
||||
@Value("${config.saml.v20.idp.receiver.endpoint}") String receiverEndpoint) {
|
||||
OpenHTTPPostDecoder decoder = new OpenHTTPPostDecoder(samlParserPool);
|
||||
decoder.setReceiverEndpoint(receiverEndpoint);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenHTTPRedirectDecoder.
|
||||
* @return openHTTPRedirectDecoder
|
||||
*/
|
||||
@Bean(name = "openHTTPRedirectDecoder")
|
||||
public OpenHTTPRedirectDecoder openHTTPRedirectDecoder(BasicParserPool samlParserPool,
|
||||
@Value("${config.saml.v20.idp.receiver.endpoint}") String receiverEndpoint) {
|
||||
OpenHTTPRedirectDecoder decoder = new OpenHTTPRedirectDecoder(samlParserPool);
|
||||
decoder.setReceiverEndpoint(receiverEndpoint);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* ExtractPostBindingAdapter.
|
||||
* @return extractPostBindingAdapter
|
||||
*/
|
||||
@Bean(name = "extractPostBindingAdapter")
|
||||
public ExtractPostBindingAdapter extractPostBindingAdapter(OpenHTTPPostDecoder openHTTPPostDecoder,
|
||||
KeyStoreLoader keyStoreLoader,IssueInstantRule issueInstantRule,MessageReplayRule messageReplayRule) {
|
||||
ExtractPostBindingAdapter adapter = new ExtractPostBindingAdapter(openHTTPPostDecoder);
|
||||
adapter.setIssueInstantRule(issueInstantRule);
|
||||
adapter.setKeyStoreLoader(keyStoreLoader);
|
||||
adapter.setMessageReplayRule(messageReplayRule);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* ExtractRedirectBindingAdapter.
|
||||
* @return extractRedirectBindingAdapter
|
||||
*/
|
||||
@Bean(name = "extractRedirectBindingAdapter")
|
||||
public ExtractRedirectBindingAdapter extractRedirectBindingAdapter(OpenHTTPRedirectDecoder openHTTPRedirectDecoder,
|
||||
KeyStoreLoader keyStoreLoader,IssueInstantRule issueInstantRule,MessageReplayRule messageReplayRule) {
|
||||
ExtractRedirectBindingAdapter adapter = new ExtractRedirectBindingAdapter(openHTTPRedirectDecoder);
|
||||
adapter.setIssueInstantRule(issueInstantRule);
|
||||
adapter.setKeyStoreLoader(keyStoreLoader);
|
||||
adapter.setMessageReplayRule(messageReplayRule);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PostSimpleSignBindingAdapter.
|
||||
* @return postSimpleSignBindingAdapter
|
||||
*/
|
||||
@Bean(name = "postSimpleSignBindingAdapter")
|
||||
public PostSimpleSignBindingAdapter postSimpleSignBindingAdapter(VelocityEngine velocityEngine,
|
||||
@Value("${config.saml.v20.idp.issuer}") String issuerEntityName) {
|
||||
PostSimpleSignBindingAdapter adapter = new PostSimpleSignBindingAdapter();
|
||||
adapter.setVelocityEngine(velocityEngine);
|
||||
adapter.setIssuerEntityName(issuerEntityName);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* PostBindingAdapter.
|
||||
* @return postBindingAdapter
|
||||
*/
|
||||
@Bean(name = "postBindingAdapter")
|
||||
public PostBindingAdapter postBindingAdapter(VelocityEngine velocityEngine,
|
||||
@Value("${config.saml.v20.idp.issuer}") String issuerEntityName) {
|
||||
PostBindingAdapter adapter = new PostBindingAdapter();
|
||||
adapter.setVelocityEngine(velocityEngine);
|
||||
adapter.setIssuerEntityName(issuerEntityName);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
@ -3,4 +3,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.maxkey.autoconfigure.ApplicationAutoConfiguration,\
|
||||
org.maxkey.autoconfigure.MvcAutoConfiguration,\
|
||||
org.maxkey.autoconfigure.KaptchaAutoConfiguration,\
|
||||
org.maxkey.autoconfigure.RedisAutoConfiguration
|
||||
org.maxkey.autoconfigure.RedisAutoConfiguration,\
|
||||
org.maxkey.autoconfigure.CasAutoConfiguration,\
|
||||
org.maxkey.autoconfigure.Oauth20AutoConfiguration,\
|
||||
org.maxkey.autoconfigure.Saml20AutoConfiguration
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<context:component-scan base-package="org.maxkey.authz.cas.endpoint" />
|
||||
|
||||
<bean id="casTicketServices" class="org.maxkey.authz.cas.endpoint.ticket.service.InMemoryTicketServices" />
|
||||
|
||||
<!--
|
||||
<bean id="casTicketServices" class="org.maxkey.authz.cas.endpoint.ticket.service.RedisTicketServices" >
|
||||
<property name="connectionFactory" ref="redisConnectionFactory"/>
|
||||
</bean>
|
||||
-->
|
||||
</beans>
|
||||
@ -1,135 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<!-- oauth.provider-->
|
||||
<context:component-scan base-package="org.maxkey.authz.oauth2.provider.endpoint" />
|
||||
<!-- oauth.provider userinfo-->
|
||||
<context:component-scan base-package="org.maxkey.authz.oauth2.provider.userinfo.endpoint" />
|
||||
|
||||
<context:component-scan base-package="org.maxkey.authz.oauth2.provider.approval.controller" />
|
||||
|
||||
<!-- OpenID Connect 1.0 -->
|
||||
<!--
|
||||
* Self-issued Provider Metadata
|
||||
*
|
||||
* http://openid.net/specs/openid-connect-core-1_0.html#SelfIssued
|
||||
* -->
|
||||
<bean id="oidcProviderMetadata" class="org.maxkey.config.oidc.OIDCProviderMetadataDetails">
|
||||
<property name="issuer" value="${config.oidc.metadata.issuer}" />
|
||||
<property name="authorizationEndpoint" value="${config.oidc.metadata.authorizationEndpoint}" />
|
||||
<property name="tokenEndpoint" value="${config.oidc.metadata.tokenEndpoint}" />
|
||||
<property name="userinfoEndpoint" value="${config.oidc.metadata.userinfoEndpoint}" />
|
||||
</bean>
|
||||
|
||||
<bean id="tokenEnhancer" class="org.maxkey.authz.oidc.idtoken.OIDCIdTokenEnhancer">
|
||||
<property name="providerMetadata" ref="oidcProviderMetadata" />
|
||||
<property name="jwtSignerService" ref="jwtSignerValidationService" />
|
||||
<property name="jwtEnDecryptionService" ref="jwtEncryptionService" />
|
||||
<property name="clientDetailsService" ref="oauth20JdbcClientDetailsService" />
|
||||
</bean>
|
||||
|
||||
<bean id="jwkSetKeyStore" class="org.maxkey.crypto.jose.keystore.JWKSetKeyStore">
|
||||
<property name="location" value="classpath:config/keystore.jwks" />
|
||||
</bean>
|
||||
|
||||
<bean id="jwtSignerValidationService" class="org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService">
|
||||
<constructor-arg name="keyStore" ref="jwkSetKeyStore" />
|
||||
<property name="defaultSignerKeyId" value="maxkey_rsa" />
|
||||
<property name="defaultSigningAlgorithmName" value="RS256" />
|
||||
</bean>
|
||||
|
||||
<bean id="jwtEncryptionService" class="org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService">
|
||||
<constructor-arg name="keyStore" ref="jwkSetKeyStore" />
|
||||
<property name="defaultAlgorithm" value="RSA1_5" />
|
||||
<property name="defaultDecryptionKeyId" value="maxkey_rsa" />
|
||||
<property name="defaultEncryptionKeyId" value="maxkey_rsa" />
|
||||
</bean>
|
||||
<!--
|
||||
<bean id="jwtLoginService" class="com.connsec.web.authentication.support.jwt.JwtLoginService">
|
||||
<property name="jwtSignerValidationService" ref="jwtSignerValidationService" />
|
||||
<property name="jwtProviderMetadata" ref="oidcProviderMetadata" />
|
||||
</bean>
|
||||
-->
|
||||
<!-- OpenID Connect 1.0 End -->
|
||||
|
||||
<!-- In Memory -->
|
||||
<bean id="oauth20AuthorizationCodeServices" class="org.maxkey.authz.oauth2.provider.code.InMemoryAuthorizationCodeServices">
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20TokenStore" class="org.maxkey.authz.oauth2.provider.token.store.InMemoryTokenStore" >
|
||||
</bean>
|
||||
|
||||
<!-- Redis
|
||||
<bean id="oauth20AuthorizationCodeServices" class="org.maxkey.authz.oauth2.provider.code.RedisAuthorizationCodeServices">
|
||||
<constructor-arg ref="redisConnectionFactory" />
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20TokenStore" class="org.maxkey.authz.oauth2.provider.token.store.RedisTokenStore" >
|
||||
<constructor-arg ref="redisConnectionFactory" />
|
||||
</bean>
|
||||
-->
|
||||
|
||||
|
||||
<bean id="converter" class="org.maxkey.authz.oauth2.provider.token.store.JwtAccessTokenConverter">
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20JdbcClientDetailsService" class="org.maxkey.authz.oauth2.provider.client.JdbcClientDetailsService">
|
||||
<constructor-arg ref="dataSource" />
|
||||
<property name="passwordEncoder" ref="passwordReciprocal"></property>
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20ClientDetailsUserService" class="org.maxkey.authz.oauth2.provider.client.ClientDetailsUserDetailsService">
|
||||
<constructor-arg ref="oauth20JdbcClientDetailsService" />
|
||||
<property name="passwordEncoder" ref="passwordReciprocal"></property>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="oauth20TokenServices" class="org.maxkey.authz.oauth2.provider.token.DefaultTokenServices">
|
||||
<property name="tokenStore" ref="oauth20TokenStore"/>
|
||||
<property name="supportRefreshToken" value="true" />
|
||||
<property name="tokenEnhancer" ref="tokenEnhancer" />
|
||||
<property name="clientDetailsService" ref="oauth20JdbcClientDetailsService" />
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20ApprovalStore" class="org.maxkey.authz.oauth2.provider.approval.TokenApprovalStore">
|
||||
<property name="tokenStore" ref="oauth20TokenStore" />
|
||||
</bean>
|
||||
|
||||
<bean id="oAuth2RequestFactory" class="org.maxkey.authz.oauth2.provider.request.DefaultOAuth2RequestFactory">
|
||||
<constructor-arg name="clientDetailsService" ref="oauth20JdbcClientDetailsService" />
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20UserApprovalHandler" class="org.maxkey.authz.oauth2.provider.approval.controller.OAuth20UserApprovalHandler">
|
||||
<property name="approvalStore" ref="oauth20ApprovalStore" />
|
||||
<property name="clientDetailsService" ref="oauth20JdbcClientDetailsService"/>
|
||||
<property name="requestFactory" ref="oAuth2RequestFactory" />
|
||||
</bean>
|
||||
|
||||
<bean id="oauth20ClientAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
|
||||
<property name="passwordEncoder">
|
||||
<bean class="org.springframework.security.crypto.password.NoOpPasswordEncoder "/>
|
||||
</property>
|
||||
<property name="userDetailsService" ref="oauth20ClientDetailsUserService"></property>
|
||||
</bean>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@ -1,153 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
|
||||
|
||||
<!-- SAML V2.0 EndPoint -->
|
||||
<context:component-scan base-package="org.maxkey.authz.saml20.provider.endpoint" />
|
||||
<!-- MetaData V2.0 EndPoint -->
|
||||
<context:component-scan base-package="org.maxkey.authz.saml20.metadata.endpoint" />
|
||||
|
||||
<bean id="samlBootstrapInitializer" class="org.opensaml.DefaultBootstrap" init-method="bootstrap"/>
|
||||
|
||||
<bean id="timeService" class="org.maxkey.authz.saml.service.TimeService" />
|
||||
|
||||
<bean id="idService" class="org.maxkey.authz.saml.service.IDService" />
|
||||
|
||||
<bean id="samlValidaotrSuite" class="org.maxkey.authz.saml20.xml.SAML2ValidatorSuite" />
|
||||
|
||||
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
|
||||
<property name="preferFileSystemAccess" value="false"/>
|
||||
<property name="velocityProperties">
|
||||
<props>
|
||||
<prop key="resource.loader">classpath</prop>
|
||||
<prop key="classpath.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="mapBasedStorageService" class="org.opensaml.util.storage.MapBasedStorageService"/>
|
||||
|
||||
<bean id="replayCache" class="org.opensaml.util.storage.ReplayCache">
|
||||
<constructor-arg ref="mapBasedStorageService"/>
|
||||
<constructor-arg value="${config.saml.v20.replay.cache.life.in.millis}"></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="messageReplayRule" class="org.opensaml.common.binding.security.MessageReplayRule">
|
||||
<constructor-arg ref="replayCache"/>
|
||||
</bean>
|
||||
|
||||
<bean id="samlParserPool" class="org.opensaml.xml.parse.BasicParserPool" >
|
||||
<property name="maxPoolSize" value="${config.saml.v20.max.parser.pool.size}" />
|
||||
</bean>
|
||||
|
||||
<!-- Decoder -->
|
||||
<bean id="openHTTPPostSimpleSignDecoder" class="org.maxkey.authz.saml20.binding.decoder.OpenHTTPPostSimpleSignDecoder">
|
||||
<constructor-arg ref="samlParserPool"/>
|
||||
<property name="receiverEndpoint" value="${config.saml.v20.idp.receiver.endpoint}" />
|
||||
</bean>
|
||||
|
||||
<bean id="openHTTPPostDecoder" class="org.maxkey.authz.saml20.binding.decoder.OpenHTTPPostDecoder">
|
||||
<constructor-arg ref="samlParserPool"/>
|
||||
<property name="receiverEndpoint" value="${config.saml.v20.idp.receiver.endpoint}" />
|
||||
</bean>
|
||||
|
||||
<bean id="openHTTPRedirectDecoder" class="org.maxkey.authz.saml20.binding.decoder.OpenHTTPRedirectDecoder">
|
||||
<constructor-arg ref="samlParserPool"/>
|
||||
<property name="receiverEndpoint" value="${config.saml.v20.idp.receiver.endpoint}" />
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="issueInstantRule" class="org.opensaml.common.binding.security.IssueInstantRule">
|
||||
<constructor-arg index="0" value="${config.saml.v20.issue.instant.check.clock.skew.in.seconds}"/>
|
||||
<constructor-arg index="1" value="${config.saml.v20.issue.instant.check.validity.time.in.seconds}"/>
|
||||
<property name="requiredRule" value="true"/>
|
||||
|
||||
</bean>
|
||||
|
||||
<!-- Binding -->
|
||||
<!-- ExtractPostBindingAdapter -->
|
||||
<bean id="extractPostBindingAdapter" class="org.maxkey.authz.saml20.binding.impl.ExtractPostBindingAdapter">
|
||||
<constructor-arg ref="openHTTPPostDecoder"/>
|
||||
<property name="keyStoreLoader" ref="keyStoreLoader" />
|
||||
<property name="issueInstantRule" ref="issueInstantRule" />
|
||||
<property name="messageReplayRule" ref="messageReplayRule" />
|
||||
</bean>
|
||||
|
||||
<!-- ExtractRedirectBindingAdapter -->
|
||||
<bean id="extractRedirectBindingAdapter" class="org.maxkey.authz.saml20.binding.impl.ExtractRedirectBindingAdapter">
|
||||
<constructor-arg ref="openHTTPRedirectDecoder"/>
|
||||
<property name="keyStoreLoader" ref="keyStoreLoader" />
|
||||
<property name="issueInstantRule" ref="issueInstantRule" />
|
||||
<property name="messageReplayRule" ref="messageReplayRule" />
|
||||
</bean>
|
||||
|
||||
<!-- PostBindingAdapter -->
|
||||
<bean id="postSimpleSignBindingAdapter" class="org.maxkey.authz.saml20.binding.impl.PostSimpleSignBindingAdapter">
|
||||
<property name="velocityEngine" ref="velocityEngine" />
|
||||
<property name="issuerEntityName" value="${config.saml.v20.idp.issuer}"/>
|
||||
</bean>
|
||||
|
||||
<!-- PostBindingAdapter -->
|
||||
<bean id="postBindingAdapter" class="org.maxkey.authz.saml20.binding.impl.PostBindingAdapter">
|
||||
<property name="velocityEngine" ref="velocityEngine" />
|
||||
<property name="issuerEntityName" ref="issuerEntityName"/>
|
||||
</bean>
|
||||
|
||||
<bean id="issuerEntityName" class="java.lang.String" >
|
||||
<constructor-arg value="${config.saml.v20.idp.issuer}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="endpointGenerator" class="org.maxkey.authz.saml.common.EndpointGenerator"></bean>
|
||||
|
||||
<bean id="authnResponseGenerator" class="org.maxkey.authz.saml20.provider.xml.AuthnResponseGenerator">
|
||||
<constructor-arg index="0" ref="issuerEntityName" />
|
||||
<constructor-arg index="1" ref="timeService" />
|
||||
<constructor-arg index="2" ref="idService" />
|
||||
</bean>
|
||||
|
||||
<bean id="keyStoreLoader" class="org.maxkey.crypto.keystore.KeyStoreLoader">
|
||||
<property name="entityName" value="${config.saml.v20.idp.issuing.entity.id}" />
|
||||
<property name="keystorePassword" value="${config.saml.v20.idp.keystore.password}" />
|
||||
<property name="keystoreFile" value="${config.saml.v20.idp.keystore}"/>
|
||||
|
||||
</bean>
|
||||
|
||||
<bean id="spKeyStoreLoader" class="org.maxkey.crypto.keystore.KeyStoreLoader">
|
||||
<property name="entityName" value="${config.saml.v20.sp.issuing.entity.id}" />
|
||||
<property name="keystorePassword" value="${config.saml.v20.sp.keystore.password}" />
|
||||
<property name="keystoreFile" value="${config.saml.v20.sp.keystore}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="spIssuingEntityName" class="java.lang.String" >
|
||||
<constructor-arg value="${config.saml.v20.sp.issuing.entity.id}"/>
|
||||
</bean>
|
||||
|
||||
<!-- Metadata -->
|
||||
<bean id="saml20Metadata" class="org.maxkey.domain.Saml20Metadata">
|
||||
<property name="orgName" value="${config.saml.v20.metadata.orgName}" />
|
||||
<property name="orgDisplayName" value="${config.saml.v20.metadata.orgDisplayName}" />
|
||||
<property name="orgURL" value="${config.saml.v20.metadata.orgURL}"/>
|
||||
<property name="company" value="${config.saml.v20.metadata.company}" />
|
||||
<property name="contactType" value="${config.saml.v20.metadata.contactType}" />
|
||||
<property name="givenName" value="${config.saml.v20.metadata.givenName}"/>
|
||||
<property name="surName" value="${config.saml.v20.metadata.surName}" />
|
||||
<property name="emailAddress" value="${config.saml.v20.metadata.emailAddress}" />
|
||||
<property name="telephoneNumber" value="${config.saml.v20.metadata.telephoneNumber}"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
<!-- BASIC Support -->
|
||||
<mvc:interceptors>
|
||||
<mvc:interceptor>
|
||||
<mvc:mapping path="/*" />
|
||||
<bean class="org.maxkey.authn.support.basic.BasicEntryPoint" >
|
||||
<property name="enable" value="${config.support.basic.enable}"></property>
|
||||
</bean>
|
||||
</mvc:interceptor>
|
||||
</mvc:interceptors>
|
||||
|
||||
</beans>
|
||||
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
|
||||
<bean id="httpHeaderSupport" class="org.maxkey.authn.support.httpheader.HttpHeaderConfig">
|
||||
<property name="enable" value="${config.support.httpheader.enable}"></property>
|
||||
<property name="headerName" value="${config.support.httpheader.headername}"></property>
|
||||
</bean>
|
||||
|
||||
<!-- HttpHeader Support -->
|
||||
<mvc:interceptors>
|
||||
<mvc:interceptor>
|
||||
<mvc:mapping path="/*" />
|
||||
<bean class="org.maxkey.authn.support.httpheader.HttpHeaderEntryPoint" />
|
||||
</mvc:interceptor>
|
||||
</mvc:interceptors>
|
||||
|
||||
</beans>
|
||||
@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/tx
|
||||
http://www.springframework.org/schema/tx/spring-tx.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
|
||||
<bean id="kerberosService" class="org.maxkey.authn.support.kerberos.RemoteKerberosService">
|
||||
<property name="kerberosProxys" >
|
||||
<list>
|
||||
<!-- default -->
|
||||
<bean class="org.maxkey.authn.support.kerberos.KerberosProxy">
|
||||
<property name="userdomain" value="${config.support.kerberos.default.userdomain}"/>
|
||||
<property name="fullUserdomain" value="${config.support.kerberos.default.fulluserdomain}"/>
|
||||
<property name="crypto" value="${config.support.kerberos.default.crypto}"/>
|
||||
<property name="redirectUri" value="${config.support.kerberos.default.redirecturi}"/>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/tx
|
||||
http://www.springframework.org/schema/tx/spring-tx.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<!-- Social Sign On Endpoint-->
|
||||
<context:component-scan base-package="org.maxkey.web.authentication.support.socialsignon" />
|
||||
|
||||
|
||||
<bean id="socialSignOnWeibo" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.sinaweibo.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.sinaweibo.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.sinaweibo.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.sinaweibo.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.sinaweibo.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.sinaweibo.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnGoogle" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.google.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.google.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.google.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.google.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.google.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.google.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnQQ" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.qq.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.qq.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.qq.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.qq.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.qq.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.qq.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnMicrosoft" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.microsoft.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.microsoft.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.microsoft.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.microsoft.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.microsoft.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.microsoft.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnFacebook" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.facebook.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.facebook.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.facebook.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.facebook.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.facebook.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.facebook.sortorder}"/>
|
||||
</bean>
|
||||
<bean id="socialSignOndingtalk" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.dingtalk.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.dingtalk.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.dingtalk.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.dingtalk.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.dingtalk.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.dingtalk.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnProviderService" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProviderService">
|
||||
<property name="socialSignOnProviders" >
|
||||
<list>
|
||||
<ref bean="socialSignOnWeibo" />
|
||||
<ref bean="socialSignOnQQ"/>
|
||||
<ref bean="socialSignOnGoogle"/>
|
||||
<ref bean="socialSignOnMicrosoft"/>
|
||||
<ref bean="socialSignOnFacebook"/>
|
||||
<ref bean="socialSignOndingtalk"/>
|
||||
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="socialsAssociateService" class="org.maxkey.authn.support.socialsignon.service.JdbcSocialsAssociateService">
|
||||
<constructor-arg ref="jdbcTemplate"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
<!-- WsFederation Support Start -->
|
||||
<bean id="wsFederationConfiguration" class="org.maxkey.authn.support.wsfederation.WsFederationConfiguration">
|
||||
<!--
|
||||
#identifier: the identifer for the ADFS server
|
||||
#url: the login url for ADFS
|
||||
#principal: the name of the attribute/assertion returned by ADFS that contains the principal's username.
|
||||
#relyingParty: the identifier of the CAS Server as it has been configured in ADFS.
|
||||
#tolerance: (optional) the amount of drift to allow when validating the timestamp on the token. Default: 10000 (ms)
|
||||
#attributeMutator: (optional) a class (defined by you) that can modify the attributes/assertions returned by the ADFS server
|
||||
#signingCertificate: ADFS's signing certificate used to validate the token/assertions issued by ADFS.
|
||||
-->
|
||||
<property name="identifier" value="${config.support.wsfederation.identifier}" />
|
||||
<property name="url" value="${config.support.wsfederation.url}" />
|
||||
<property name="logoutUrl" value="${config.support.wsfederation.logoutUrl}" />
|
||||
<property name="principal" value="${config.support.wsfederation.principal}" />
|
||||
<property name="relyingParty" value="${config.support.wsfederation.relyingParty}" />
|
||||
<property name="tolerance" value="${config.support.wsfederation.tolerance}" />
|
||||
<property name="upnSuffix" value="${config.support.wsfederation.upn.suffix}" />
|
||||
<property name="attributeMutator">
|
||||
<bean class="org.maxkey.authn.support.wsfederation.WsFedAttributeMutatorImpl" />
|
||||
</property>
|
||||
<property name="signingCertificates">
|
||||
<list>
|
||||
<value>classpath:${config.support.wsfederation.signingCertificate}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="wsFederationService" class="org.maxkey.authn.support.wsfederation.WsFederationServiceImpl">
|
||||
<property name="wsFederationConfiguration" ref="wsFederationConfiguration" />
|
||||
</bean>
|
||||
|
||||
<!-- WsFederation Support End -->
|
||||
|
||||
</beans>
|
||||
@ -18,30 +18,160 @@
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<!-- authn support -->
|
||||
<!-- Authentication -->
|
||||
<import resource="maxkey-support-httpheader.xml"/>
|
||||
<import resource="maxkey-support-basic.xml"/>
|
||||
<import resource="maxkey-support-kerberos.xml"/>
|
||||
<import resource="maxkey-support-social.xml"/>
|
||||
<!--
|
||||
<import resource="maxkey-support-wsfederation.xml"/>
|
||||
<!-- Authentication Extends support -->
|
||||
<!-- HttpHeader Support Start-->
|
||||
<bean id="httpHeaderSupport" class="org.maxkey.authn.support.httpheader.HttpHeaderConfig">
|
||||
<property name="enable" value="${config.support.httpheader.enable}"></property>
|
||||
<property name="headerName" value="${config.support.httpheader.headername}"></property>
|
||||
</bean>
|
||||
|
||||
<mvc:interceptors>
|
||||
<mvc:interceptor>
|
||||
<mvc:mapping path="/*" />
|
||||
<bean class="org.maxkey.authn.support.httpheader.HttpHeaderEntryPoint" />
|
||||
</mvc:interceptor>
|
||||
</mvc:interceptors>
|
||||
<!-- HttpHeader Support End-->
|
||||
|
||||
<!-- BASIC Support Start-->
|
||||
<mvc:interceptors>
|
||||
<mvc:interceptor>
|
||||
<mvc:mapping path="/*" />
|
||||
<bean class="org.maxkey.authn.support.basic.BasicEntryPoint" >
|
||||
<property name="enable" value="${config.support.basic.enable}"></property>
|
||||
</bean>
|
||||
</mvc:interceptor>
|
||||
</mvc:interceptors>
|
||||
<!-- BASIC Support End-->
|
||||
|
||||
<!-- KERBEROS Support Start-->
|
||||
<bean id="kerberosService" class="org.maxkey.authn.support.kerberos.RemoteKerberosService">
|
||||
<property name="kerberosProxys" >
|
||||
<list>
|
||||
<!-- default -->
|
||||
<bean class="org.maxkey.authn.support.kerberos.KerberosProxy">
|
||||
<property name="userdomain" value="${config.support.kerberos.default.userdomain}"/>
|
||||
<property name="fullUserdomain" value="${config.support.kerberos.default.fulluserdomain}"/>
|
||||
<property name="crypto" value="${config.support.kerberos.default.crypto}"/>
|
||||
<property name="redirectUri" value="${config.support.kerberos.default.redirecturi}"/>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
<!-- KERBEROS Support End-->
|
||||
|
||||
<!-- WsFederation Support Start -->
|
||||
<!--
|
||||
#identifier: the identifer for the ADFS server
|
||||
#url: the login url for ADFS
|
||||
#principal: the name of the attribute/assertion returned by ADFS that contains the principal's username.
|
||||
#relyingParty: the identifier of the CAS Server as it has been configured in ADFS.
|
||||
#tolerance: (optional) the amount of drift to allow when validating the timestamp on the token. Default: 10000 (ms)
|
||||
#attributeMutator: (optional) a class (defined by you) that can modify the attributes/assertions returned by the ADFS server
|
||||
#signingCertificate: ADFS's signing certificate used to validate the token/assertions issued by ADFS.
|
||||
-->
|
||||
<!--
|
||||
<bean id="wsFederationConfiguration" class="org.maxkey.authn.support.wsfederation.WsFederationConfiguration">
|
||||
<property name="identifier" value="${config.support.wsfederation.identifier}" />
|
||||
<property name="url" value="${config.support.wsfederation.url}" />
|
||||
<property name="logoutUrl" value="${config.support.wsfederation.logoutUrl}" />
|
||||
<property name="principal" value="${config.support.wsfederation.principal}" />
|
||||
<property name="relyingParty" value="${config.support.wsfederation.relyingParty}" />
|
||||
<property name="tolerance" value="${config.support.wsfederation.tolerance}" />
|
||||
<property name="upnSuffix" value="${config.support.wsfederation.upn.suffix}" />
|
||||
<property name="attributeMutator">
|
||||
<bean class="org.maxkey.authn.support.wsfederation.WsFedAttributeMutatorImpl" />
|
||||
</property>
|
||||
<property name="signingCertificates">
|
||||
<list>
|
||||
<value>classpath:${config.support.wsfederation.signingCertificate}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- single sign on protocol -->
|
||||
<!-- Single Sign On for application -->
|
||||
<context:component-scan base-package="org.maxkey.authz.endpoint" />
|
||||
<context:component-scan base-package="org.maxkey.authz.desktop.endpoint" />
|
||||
<context:component-scan base-package="org.maxkey.authz.exapi.endpoint" />
|
||||
<context:component-scan base-package="org.maxkey.authz.formbased.endpoint" />
|
||||
<context:component-scan base-package="org.maxkey.authz.ltpa.endpoint" />
|
||||
<context:component-scan base-package="org.maxkey.authz.token.endpoint" />
|
||||
<bean id="wsFederationService" class="org.maxkey.authn.support.wsfederation.WsFederationServiceImpl">
|
||||
<property name="wsFederationConfiguration" ref="wsFederationConfiguration" />
|
||||
</bean>
|
||||
-->
|
||||
<!-- WsFederation Support End -->
|
||||
|
||||
<!-- Social Sign On Support Start-->
|
||||
<!-- Social Sign On Endpoint-->
|
||||
<context:component-scan base-package="org.maxkey.web.authentication.support.socialsignon" />
|
||||
|
||||
|
||||
<bean id="socialSignOnWeibo" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.sinaweibo.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.sinaweibo.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.sinaweibo.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.sinaweibo.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.sinaweibo.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.sinaweibo.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnGoogle" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.google.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.google.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.google.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.google.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.google.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.google.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnQQ" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.qq.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.qq.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.qq.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.qq.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.qq.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.qq.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<import resource="maxkey-protocol-cas.xml"/>
|
||||
<import resource="maxkey-protocol-saml.xml"/>
|
||||
<import resource="maxkey-protocol-oauth2.0.xml"/>
|
||||
<bean id="socialSignOnMicrosoft" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.microsoft.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.microsoft.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.microsoft.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.microsoft.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.microsoft.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.microsoft.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="socialSignOnFacebook" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.facebook.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.facebook.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.facebook.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.facebook.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.facebook.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.facebook.sortorder}"/>
|
||||
</bean>
|
||||
<bean id="socialSignOndingtalk" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider">
|
||||
<property name="provider" value="${config.socialsignon.dingtalk.provider}"/>
|
||||
<property name="providerName" value="${config.socialsignon.dingtalk.provider.name}"/>
|
||||
<property name="icon" value="${config.socialsignon.dingtalk.icon}"/>
|
||||
<property name="clientId" value="${config.socialsignon.dingtalk.client.id}"/>
|
||||
<property name="clientSecret" value="${config.socialsignon.dingtalk.client.secret}"/>
|
||||
<property name="sortOrder" value="${config.socialsignon.dingtalk.sortorder}"/>
|
||||
</bean>
|
||||
|
||||
<!-- Basic Authn for user login -->
|
||||
<bean id="socialSignOnProviderService" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProviderService">
|
||||
<property name="socialSignOnProviders" >
|
||||
<list>
|
||||
<ref bean="socialSignOnWeibo" />
|
||||
<ref bean="socialSignOnQQ"/>
|
||||
<ref bean="socialSignOnGoogle"/>
|
||||
<ref bean="socialSignOnMicrosoft"/>
|
||||
<ref bean="socialSignOnFacebook"/>
|
||||
<ref bean="socialSignOndingtalk"/>
|
||||
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="socialsAssociateService" class="org.maxkey.authn.support.socialsignon.service.JdbcSocialsAssociateService">
|
||||
<constructor-arg ref="jdbcTemplate"/>
|
||||
</bean>
|
||||
<!-- Social Sign On Support End -->
|
||||
|
||||
<!-- enable autowire -->
|
||||
<context:annotation-config />
|
||||
|
||||
@ -95,8 +225,6 @@
|
||||
<mvc:mapping path="/authz/cas/granting"/>
|
||||
<bean class="org.maxkey.web.interceptor.HistoryLoginAppAdapter" />
|
||||
</mvc:interceptor>
|
||||
|
||||
|
||||
<ref bean="localeChangeInterceptor" />
|
||||
</mvc:interceptors>
|
||||
|
||||
|
||||
@ -1,18 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Second Protected</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<s:BasePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base/>/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
<#include "formbased_common.ftl">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form id="apppasswodprotectedsubmit" name="apppasswodprotectedsubmit" action="<s:Base/>/authz/protected" method="post">
|
||||
<form id="apppasswodprotectedsubmit" name="apppasswodprotectedsubmit" action="<@base />/authz/protected" method="post">
|
||||
<table style="margin: auto;width:50%">
|
||||
<tr>
|
||||
<td><@locale code="userinfo.appLoginPassword" /></td>
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>QQ SSO Execute</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<#include "formbased_common.ftl">
|
||||
<script>
|
||||
|
||||
function sleep(milliseconds) {
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<#include "formbased_common.ftl">
|
||||
<title>Desktop SSO Execute</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
@ -1,13 +1,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<s:Base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<@basePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base/>/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
<#include "formbased_common.ftl">
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
<#if isExtendAttr >
|
||||
@ -0,0 +1,12 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<@basePath/>"/>
|
||||
|
||||
<script src ="<@base />/static/jquery/jquery-3.5.0.min.js" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/jsbn.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/prng4.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/rng.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/rsa.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/base64.js"></script>
|
||||
@ -1,18 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<s:BasePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base />/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/jsbn.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/prng4.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/rng.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/rsa.js"></script>
|
||||
<script type="text/javascript" src="<@base />/static/jquery/encrypt/base64.js"></script>
|
||||
<#include "formbased_common.ftl">
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
var public_ts=(new Date()).getTime();
|
||||
|
||||
@ -1,14 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<s:BasePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base />/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
<#include "formbased_common.ftl">
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
<#if true==isExtendAttr>
|
||||
|
||||
@ -1,14 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<s:Base />/static/images/favicon.ico"/>
|
||||
<base href="<s:BasePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base/>/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
<#include "formbased_common.ftl">
|
||||
|
||||
<script type="text/javascript">
|
||||
function redirect2link( ){
|
||||
window.top.location.href="${loginUrl}";
|
||||
|
||||
@ -1,14 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<s:BasePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base/>/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
<#include "formbased_common.ftl">
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
<#if true == isExtendAttr>
|
||||
|
||||
@ -1,14 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>Form-Based SSO Submit</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<@basePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base/>/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
<#include "formbased_common.ftl">
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
window.top.location.href ="https://note.youdao.com/login/acc/login?username=${username}&password=${password}&app=web&product=YNOTE&tp=urstoken&cf=2&fr=1&systemName=&deviceType=&ru=http://note.youdao.com/web/&er=http://note.youdao.com/web/?&systemName=Windows&deviceType=WindowsPC×tamp=${currentTime}";
|
||||
@ -1,14 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<#include "formbased_common.ftl">
|
||||
<title>SSO Credential Init</title>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<base href="<s:BasePath/>"/>
|
||||
|
||||
<script type="text/javascript" src="<@base/>/static/jquery/jquery-1.11.2.min.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<#include "formbased_common.ftl">
|
||||
<title>Token-Based SSO Submit</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="document.forms[0].submit()" style="display:none">
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<#include "formbased_common.ftl">
|
||||
<title>Token-Based SSO Submit</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
|
||||
<link type="text/css" rel="stylesheet" href="<@base />/static/css/base.css"/>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="document.forms[0].submit()" style="display:none">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user