Browse Source

v 1.5.0 RC2

v 1.5.0 RC2
shimingxy 5 years ago
parent
commit
27e0c0b376
35 changed files with 1553 additions and 1324 deletions
  1. 1 1
      docs/authn/social.md
  2. 3 6
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/service/JdbcTicketServices.java
  3. 1 1
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/FormBasedAuthorizeEndpoint.java
  4. 1 1
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNetease163EmailAdapter.java
  5. 1 1
      maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNeteaseNoteYoudaoAdapter.java
  6. 61 56
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/JdbcAuthorizationCodeServices.java
  7. 383 390
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JdbcTokenStore.java
  8. 194 194
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JwtAccessTokenConverter.java
  9. 8 1
      maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyConfig.java
  10. 58 0
      maxkey-web-maxkey/src/main/java/org/maxkey/autoconfigure/CasAutoConfiguration.java
  11. 334 0
      maxkey-web-maxkey/src/main/java/org/maxkey/autoconfigure/Oauth20AutoConfiguration.java
  12. 322 0
      maxkey-web-maxkey/src/main/java/org/maxkey/autoconfigure/Saml20AutoConfiguration.java
  13. 4 1
      maxkey-web-maxkey/src/main/resources/META-INF/spring.factories
  14. 0 27
      maxkey-web-maxkey/src/main/resources/spring/maxkey-protocol-cas.xml
  15. 0 135
      maxkey-web-maxkey/src/main/resources/spring/maxkey-protocol-oauth2.0.xml
  16. 0 153
      maxkey-web-maxkey/src/main/resources/spring/maxkey-protocol-saml.xml
  17. 0 31
      maxkey-web-maxkey/src/main/resources/spring/maxkey-support-basic.xml
  18. 0 35
      maxkey-web-maxkey/src/main/resources/spring/maxkey-support-httpheader.xml
  19. 0 36
      maxkey-web-maxkey/src/main/resources/spring/maxkey-support-kerberos.xml
  20. 0 97
      maxkey-web-maxkey/src/main/resources/spring/maxkey-support-social.xml
  21. 0 55
      maxkey-web-maxkey/src/main/resources/spring/maxkey-support-wsfederation.xml
  22. 150 22
      maxkey-web-maxkey/src/main/resources/spring/maxkey.xml
  23. 2 9
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/app_password_protected.ftl
  24. 1 4
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/desktop_qq_sso_execute.ftl
  25. 1 3
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/desktop_sso_execute.ftl
  26. 2 8
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_163email_sso_submint.ftl
  27. 12 0
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_common.ftl
  28. 1 12
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_qq_exmail_sso_submint.ftl
  29. 2 8
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_redirect_post_submint.ftl
  30. 2 8
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_redirect_submint.ftl
  31. 2 8
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_sso_submint.ftl
  32. 2 8
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_wy_youdao_sso_submint.ftl
  33. 1 7
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/init_sso_credential.ftl
  34. 2 3
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/tokenbased_jwt_sso_submint.ftl
  35. 2 3
      maxkey-web-maxkey/src/main/resources/templates/views/authorize/tokenbased_sso_submint.ftl

+ 1 - 1
docs/authn/social.md

@@ -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">
 &lt;bean id="socialSignOnWeibo" class="org.maxkey.authn.support.socialsignon.service.SocialSignOnProvider"&gt;

+ 3 - 6
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/ticket/service/JdbcTicketServices.java

@@ -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

+ 1 - 1
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/FormBasedAuthorizeEndpoint.java

@@ -73,7 +73,7 @@ public class FormBasedAuthorizeEndpoint  extends AuthorizeBaseEndpoint{
 					modelAndView);
 		}
 		
-		
+		_logger.debug("FormBased View Name " + modelAndView.getViewName());
 		
 		return modelAndView;
 	}

+ 1 - 1
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNetease163EmailAdapter.java

@@ -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());

+ 1 - 1
maxkey-protocols/maxkey-protocol-formbased/src/main/java/org/maxkey/authz/formbased/endpoint/adapter/FormBasedNeteaseNoteYoudaoAdapter.java

@@ -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()));

+ 61 - 56
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/code/JdbcAuthorizationCodeServices.java

@@ -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 String selectAuthenticationSql = DEFAULT_SELECT_STATEMENT;
-	private String insertAuthenticationSql = DEFAULT_INSERT_STATEMENT;
-	private String deleteAuthenticationSql = DEFAULT_DELETE_STATEMENT;
-
-	private final JdbcTemplate jdbcTemplate;
-
-	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 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;
-		}
-
-		if (authentication != null) {
-			jdbcTemplate.update(deleteAuthenticationSql, code);
-		}
-
-		return authentication;
-	}
-
-	public void setSelectAuthenticationSql(String selectAuthenticationSql) {
-		this.selectAuthenticationSql = selectAuthenticationSql;
-	}
-
-	public void setInsertAuthenticationSql(String insertAuthenticationSql) {
-		this.insertAuthenticationSql = insertAuthenticationSql;
-	}
-
-	public void setDeleteAuthenticationSql(String deleteAuthenticationSql) {
-		this.deleteAuthenticationSql = deleteAuthenticationSql;
-	}
+    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 final JdbcTemplate jdbcTemplate;
+
+    public JdbcAuthorizationCodeServices(DataSource dataSource) {
+        Assert.notNull(dataSource, "DataSource required");
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+    }
+
+    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;
+
+        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);
+        }
+
+        return authentication;
+    }
+
+    public void setSelectAuthenticationSql(String selectAuthenticationSql) {
+        this.selectAuthenticationSql = selectAuthenticationSql;
+    }
+
+    public void setInsertAuthenticationSql(String insertAuthenticationSql) {
+        this.insertAuthenticationSql = insertAuthenticationSql;
+    }
+
+    public void setDeleteAuthenticationSql(String deleteAuthenticationSql) {
+        this.deleteAuthenticationSql = deleteAuthenticationSql;
+    }
 }

+ 383 - 390
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JdbcTokenStore.java

@@ -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;
+    }
 }

+ 194 - 194
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/maxkey/authz/oauth2/provider/token/store/JwtAccessTokenConverter.java

@@ -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;
+    }
 }

+ 8 - 1
maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyConfig.java

@@ -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);

+ 58 - 0
maxkey-web-maxkey/src/main/java/org/maxkey/autoconfigure/CasAutoConfiguration.java

@@ -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
+        
+    }
+}

+ 334 - 0
maxkey-web-maxkey/src/main/java/org/maxkey/autoconfigure/Oauth20AutoConfiguration.java

@@ -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
+        
+    }
+}

+ 322 - 0
maxkey-web-maxkey/src/main/java/org/maxkey/autoconfigure/Saml20AutoConfiguration.java

@@ -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
+        
+    }
+}

+ 4 - 1
maxkey-web-maxkey/src/main/resources/META-INF/spring.factories

@@ -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

+ 0 - 27
maxkey-web-maxkey/src/main/resources/spring/maxkey-protocol-cas.xml

@@ -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>

+ 0 - 135
maxkey-web-maxkey/src/main/resources/spring/maxkey-protocol-oauth2.0.xml

@@ -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>

+ 0 - 153
maxkey-web-maxkey/src/main/resources/spring/maxkey-protocol-saml.xml

@@ -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>

+ 0 - 31
maxkey-web-maxkey/src/main/resources/spring/maxkey-support-basic.xml

@@ -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>

+ 0 - 35
maxkey-web-maxkey/src/main/resources/spring/maxkey-support-httpheader.xml

@@ -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>

+ 0 - 36
maxkey-web-maxkey/src/main/resources/spring/maxkey-support-kerberos.xml

@@ -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>

+ 0 - 97
maxkey-web-maxkey/src/main/resources/spring/maxkey-support-social.xml

@@ -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>

+ 0 - 55
maxkey-web-maxkey/src/main/resources/spring/maxkey-support-wsfederation.xml

@@ -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>

+ 150 - 22
maxkey-web-maxkey/src/main/resources/spring/maxkey.xml

@@ -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>
+    
+    <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" />
+    
     
-    <!-- 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="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> 
+    
+    <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>
     
-	<!-- Basic Authn  for user login -->
+    <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>
 

+ 2 - 9
maxkey-web-maxkey/src/main/resources/templates/views/authorize/app_password_protected.ftl

@@ -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 - 4
maxkey-web-maxkey/src/main/resources/templates/views/authorize/desktop_qq_sso_execute.ftl

@@ -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 - 3
maxkey-web-maxkey/src/main/resources/templates/views/authorize/desktop_sso_execute.ftl

@@ -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>
 
 

+ 2 - 8
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_netease_163email_sso_submint.ftl → maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_163email_sso_submint.ftl

@@ -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 >

+ 12 - 0
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_common.ftl

@@ -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 - 12
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_qq_exmail_sso_submint.ftl

@@ -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();

+ 2 - 8
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_redirect_post_submint.ftl

@@ -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>

+ 2 - 8
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_redirect_submint.ftl

@@ -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}";

+ 2 - 8
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_sso_submint.ftl

@@ -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>

+ 2 - 8
maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_netease_noteyoudao_sso_submint.ftl → maxkey-web-maxkey/src/main/resources/templates/views/authorize/formbased_wy_youdao_sso_submint.ftl

@@ -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&timestamp=${currentTime}";

+ 1 - 7
maxkey-web-maxkey/src/main/resources/templates/views/authorize/init_sso_credential.ftl

@@ -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>

+ 2 - 3
maxkey-web-maxkey/src/main/resources/templates/views/authorize/tokenbased_jwt_sso_submint.ftl

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

+ 2 - 3
maxkey-web-maxkey/src/main/resources/templates/views/authorize/tokenbased_sso_submint.ftl

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