From a3bbe775a05ff807f346627d8e5ef0d1f391948f Mon Sep 17 00:00:00 2001 From: monkeyk7 Date: Fri, 5 Jul 2019 00:47:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BD=BF=E7=94=A8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90AccessToken=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ntCredentialsInlineAccessTokenInvoker.java | 28 ++++ .../business/InlineAccessTokenInvoker.java | 158 ++++++++++++++++++ .../PasswordInlineAccessTokenInvoker.java | 29 ++++ .../RefreshTokenInlineAccessTokenInvoker.java | 28 ++++ .../sos/service/dto/AccessTokenDto.java | 107 ++++++++++++ .../service/dto/OauthClientDetailsDto.java | 2 + .../monkeyk/sos/service/dto/UserJsonDto.java | 2 + 7 files changed, 354 insertions(+) create mode 100644 src/main/java/com/monkeyk/sos/service/business/ClientCredentialsInlineAccessTokenInvoker.java create mode 100644 src/main/java/com/monkeyk/sos/service/business/InlineAccessTokenInvoker.java create mode 100644 src/main/java/com/monkeyk/sos/service/business/PasswordInlineAccessTokenInvoker.java create mode 100644 src/main/java/com/monkeyk/sos/service/business/RefreshTokenInlineAccessTokenInvoker.java create mode 100644 src/main/java/com/monkeyk/sos/service/dto/AccessTokenDto.java diff --git a/src/main/java/com/monkeyk/sos/service/business/ClientCredentialsInlineAccessTokenInvoker.java b/src/main/java/com/monkeyk/sos/service/business/ClientCredentialsInlineAccessTokenInvoker.java new file mode 100644 index 0000000..8f26763 --- /dev/null +++ b/src/main/java/com/monkeyk/sos/service/business/ClientCredentialsInlineAccessTokenInvoker.java @@ -0,0 +1,28 @@ +package com.monkeyk.sos.service.business; + +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter; + +/** + * 2019/7/5 + *

+ *

+ * grant_type = client_credentials + * + * @author Shengzhao Li + * @since 2.0.1 + */ +public class ClientCredentialsInlineAccessTokenInvoker extends InlineAccessTokenInvoker { + + + public ClientCredentialsInlineAccessTokenInvoker() { + } + + @Override + protected TokenGranter getTokenGranter(OAuth2RequestFactory oAuth2RequestFactory) { + return new ClientCredentialsTokenGranter(this.tokenServices, this.clientDetailsService, oAuth2RequestFactory); + } + + +} diff --git a/src/main/java/com/monkeyk/sos/service/business/InlineAccessTokenInvoker.java b/src/main/java/com/monkeyk/sos/service/business/InlineAccessTokenInvoker.java new file mode 100644 index 0000000..f91c4d1 --- /dev/null +++ b/src/main/java/com/monkeyk/sos/service/business/InlineAccessTokenInvoker.java @@ -0,0 +1,158 @@ +package com.monkeyk.sos.service.business; + +import com.monkeyk.sos.service.dto.AccessTokenDto; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.*; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.util.Assert; + +import java.util.Map; + +import static org.springframework.security.oauth2.common.util.OAuth2Utils.CLIENT_ID; +import static org.springframework.security.oauth2.common.util.OAuth2Utils.GRANT_TYPE; +import static org.springframework.security.oauth2.common.util.OAuth2Utils.SCOPE; + +/** + * 2019/7/5 + * + * @author Shengzhao Li + * @see org.springframework.security.oauth2.provider.endpoint.TokenEndpoint + * @since 2.0.1 + */ +public abstract class InlineAccessTokenInvoker implements InitializingBean { + + + private static final Logger LOG = LoggerFactory.getLogger(InlineAccessTokenInvoker.class); + + + protected transient AuthenticationManager authenticationManager; + + protected transient AuthorizationServerTokenServices tokenServices; + protected transient ClientDetailsService clientDetailsService; + + + public InlineAccessTokenInvoker() { + } + + + /** + * 根据不同的 params 生成 AccessTokenDto + *

+ * 适合以下几类 grant_type: + * password + * refresh_token + * client_credentials + * + * @param params Params Map + * @return AccessTokenDto instance + */ + public AccessTokenDto invoke(Map params) { + + if (params == null || params.isEmpty()) { + throw new IllegalStateException("Null or empty params"); + } + + String clientId = validateParams(params); + + final ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); + if (clientDetails == null) { + LOG.warn("Not found ClientDetails by clientId: {}", clientId); + return null; + } + + OAuth2RequestFactory oAuth2RequestFactory = createOAuth2RequestFactory(); + TokenGranter tokenGranter = getTokenGranter(oAuth2RequestFactory); + LOG.debug("Use TokenGranter: {}", tokenGranter); + + TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(params, clientDetails); + final OAuth2AccessToken oAuth2AccessToken = tokenGranter.grant(getGrantType(params), tokenRequest); + + AccessTokenDto accessTokenDto = new AccessTokenDto(oAuth2AccessToken); + LOG.debug("Invoked accessTokenDto: {}", accessTokenDto); + return accessTokenDto; + } + + + /** + * 校验各类 grant_type时 需要的参数 + * + * @param params params + * @return clientId + */ + protected String validateParams(Map params) { + //validate client_id + String clientId = params.get(CLIENT_ID); + if (StringUtils.isBlank(clientId)) { + throw new IllegalStateException("Null or empty '" + CLIENT_ID + "' from params"); + } + + //validate grant_type + final String grantType = params.get(GRANT_TYPE); + if (StringUtils.isBlank(grantType)) { + throw new IllegalStateException("Null or empty '" + GRANT_TYPE + "' from params"); + } + + //validate scope + final String scope = params.get(SCOPE); + if (StringUtils.isBlank(scope)) { + throw new IllegalStateException("Null or empty '" + SCOPE + "' from params"); + } + + return clientId; + } + + + /** + * Get grant_type from params + * + * @param params Map + * @return Grant Type + */ + protected String getGrantType(Map params) { + return params.get(GRANT_TYPE); + } + + + /** + * Get TokenGranter implement + * + * @return TokenGranter + */ + protected abstract TokenGranter getTokenGranter(OAuth2RequestFactory oAuth2RequestFactory); + + /** + * Create OAuth2RequestFactory + * + * @return OAuth2RequestFactory instance + */ + protected OAuth2RequestFactory createOAuth2RequestFactory() { + return new DefaultOAuth2RequestFactory(this.clientDetailsService); + } + + + public void setAuthenticationManager(AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public void setTokenServices(AuthorizationServerTokenServices tokenServices) { + this.tokenServices = tokenServices; + } + + public void setClientDetailsService(ClientDetailsService clientDetailsService) { + this.clientDetailsService = clientDetailsService; + } + + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.authenticationManager, "authenticationManager is null"); + Assert.notNull(this.tokenServices, "tokenServices is null"); + + Assert.notNull(this.clientDetailsService, "clientDetailsService is null"); + } +} diff --git a/src/main/java/com/monkeyk/sos/service/business/PasswordInlineAccessTokenInvoker.java b/src/main/java/com/monkeyk/sos/service/business/PasswordInlineAccessTokenInvoker.java new file mode 100644 index 0000000..aaf5ddf --- /dev/null +++ b/src/main/java/com/monkeyk/sos/service/business/PasswordInlineAccessTokenInvoker.java @@ -0,0 +1,29 @@ +package com.monkeyk.sos.service.business; + +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter; + +/** + * 2019/7/5 + *

+ *

+ * grant_type = password + * + * @author Shengzhao Li + * @since 2.0.1 + */ +public class PasswordInlineAccessTokenInvoker extends InlineAccessTokenInvoker { + + + public PasswordInlineAccessTokenInvoker() { + } + + @Override + protected TokenGranter getTokenGranter(OAuth2RequestFactory oAuth2RequestFactory) { + return new ResourceOwnerPasswordTokenGranter(this.authenticationManager, this.tokenServices, this.clientDetailsService, oAuth2RequestFactory); + } + + + +} diff --git a/src/main/java/com/monkeyk/sos/service/business/RefreshTokenInlineAccessTokenInvoker.java b/src/main/java/com/monkeyk/sos/service/business/RefreshTokenInlineAccessTokenInvoker.java new file mode 100644 index 0000000..4b66c9d --- /dev/null +++ b/src/main/java/com/monkeyk/sos/service/business/RefreshTokenInlineAccessTokenInvoker.java @@ -0,0 +1,28 @@ +package com.monkeyk.sos.service.business; + +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenGranter; +import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter; + +/** + * 2019/7/5 + *

+ *

+ * grant_type = refresh_token + * + * @author Shengzhao Li + * @since 2.0.1 + */ +public class RefreshTokenInlineAccessTokenInvoker extends InlineAccessTokenInvoker { + + + public RefreshTokenInlineAccessTokenInvoker() { + } + + @Override + protected TokenGranter getTokenGranter(OAuth2RequestFactory oAuth2RequestFactory) { + return new RefreshTokenGranter(this.tokenServices, this.clientDetailsService, oAuth2RequestFactory); + } + + +} diff --git a/src/main/java/com/monkeyk/sos/service/dto/AccessTokenDto.java b/src/main/java/com/monkeyk/sos/service/dto/AccessTokenDto.java new file mode 100644 index 0000000..cb97b84 --- /dev/null +++ b/src/main/java/com/monkeyk/sos/service/dto/AccessTokenDto.java @@ -0,0 +1,107 @@ +package com.monkeyk.sos.service.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang.StringUtils; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2RefreshToken; + +import java.io.Serializable; + +/** + * 2019/7/5 + *

+ * {"access_token":"iuy0fbfe-da2c-4840-8b66-848168ad8d00","token_type":"bearer","refresh_token":"9406e12f-d62e-42bd-ad40-0206d94ae7ds","expires_in":7199,"scope":"read"} + * + * @author Shengzhao Li + * @since 2.0.1 + */ +public class AccessTokenDto implements Serializable { + private static final long serialVersionUID = -8894979171517528312L; + + + @JsonProperty("access_token") + private String accessToken; + + @JsonProperty("token_type") + private String tokenType; + + @JsonProperty("refresh_token") + private String refreshToken; + + @JsonProperty("scope") + private String scope; + + @JsonProperty("expires_in") + private int expiresIn; + + + public AccessTokenDto() { + } + + + public AccessTokenDto(OAuth2AccessToken token) { + this.accessToken = token.getValue(); + this.expiresIn = token.getExpiresIn(); + + this.scope = StringUtils.join(token.getScope(), ","); + this.tokenType = token.getTokenType(); + + final OAuth2RefreshToken oAuth2RefreshToken = token.getRefreshToken(); + if (oAuth2RefreshToken != null) { + this.refreshToken = oAuth2RefreshToken.getValue(); + } + } + + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public String getTokenType() { + return tokenType; + } + + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } + + public String getRefreshToken() { + return refreshToken; + } + + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public int getExpiresIn() { + return expiresIn; + } + + public void setExpiresIn(int expiresIn) { + this.expiresIn = expiresIn; + } + + @Override + public String toString() { + return "{" + + "accessToken='" + accessToken + '\'' + + ", tokenType='" + tokenType + '\'' + + ", refreshToken='" + refreshToken + '\'' + + ", scope='" + scope + '\'' + + ", expiresIn=" + expiresIn + + '}'; + } + +} diff --git a/src/main/java/com/monkeyk/sos/service/dto/OauthClientDetailsDto.java b/src/main/java/com/monkeyk/sos/service/dto/OauthClientDetailsDto.java index 9ddeb41..bae6762 100644 --- a/src/main/java/com/monkeyk/sos/service/dto/OauthClientDetailsDto.java +++ b/src/main/java/com/monkeyk/sos/service/dto/OauthClientDetailsDto.java @@ -16,6 +16,8 @@ import java.util.List; public class OauthClientDetailsDto implements Serializable { + private static final long serialVersionUID = 4011292111995231569L; + private String createTime; private boolean archived; diff --git a/src/main/java/com/monkeyk/sos/service/dto/UserJsonDto.java b/src/main/java/com/monkeyk/sos/service/dto/UserJsonDto.java index 2184996..76a6b08 100644 --- a/src/main/java/com/monkeyk/sos/service/dto/UserJsonDto.java +++ b/src/main/java/com/monkeyk/sos/service/dto/UserJsonDto.java @@ -13,6 +13,8 @@ import java.util.List; public class UserJsonDto implements Serializable { + private static final long serialVersionUID = -704681024783524371L; + private String guid; private boolean archived;