Spring Oauth2 - 从@RequestParam自定义TokenEndpoint到@RequestBody

时间:2018-06-06 09:55:15

标签: spring-boot spring-security spring-security-oauth2

我使用Spring-Security的标准配置,这是我的pom.xml:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath></relativePath>
    </parent>

<dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
</dependencies>

我必须更改标准令牌请求:

原始令牌请求:

@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException

终止令牌请求

@RequestMapping(value = "/oauth/login", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestBody UserLogin userLogin) throws HttpRequestMethodNotSupportedException

可能吗?

我像这样扩展TokenEndpoint但是没有工作:

public class CustomTokenEndpoint extends TokenEndpoint {

@RequestMapping(value = "/oauth/login", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestBody UserLogin userLogin) throws HttpRequestMethodNotSupportedException {
        return postAccessToken(principal, userLogin.getParameters());
    }
}

1 个答案:

答案 0 :(得分:0)

它不会像这样工作,因为您的自定义端点类不会在Spring过滤器链中加载。无需延长TokenEndpoint。您可以创建一个新端点,使其完成原始端点/oauth/token所做的事情。

以下代码应该为您提供一个良好的开端。请参阅此代码以了解新端点需要执行的操作。这类似于TokenEndpoint#postAccessToken(...)

@RequestMapping(value = "/oauth/login", method = RequestMethod.POST)
    public ResponseEntity<OAuth2AccessToken> postAccessToken(final Principal principal, @RequestBody final UserLogin userLogin) throws HttpRequestMethodNotSupportedException {
        if (!(principal instanceof Authentication)) {
            throw new InsufficientAuthenticationException("Client authentication information is missing.");
        }

        final Authentication client = (Authentication) principal;
        if (!client.isAuthenticated()) {
            throw new InsufficientAuthenticationException("The client is not authenticated.");
        }
        String clientId = client.getName();
        if (client instanceof OAuth2Authentication) {
            // Might be a client and user combined authentication
            clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId();
        }

        final ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId);
        final TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, authenticatedClient);

        final Map<String, String> parameters = new HashMap<>();
        parameters.put("username", userLogin.getUsername());
        parameters.put("password", userLogin.getPassword());
        parameters.put("grant_type", userLogin.getGrantType());
        parameters.put("refresh_token", userLogin.getRefreshToken());
        parameters.put("scope", userLogin.getScope());

        if (StringUtils.isNotBlank(clientId)) {
            // Only validate the client details if a client authenticated during this request.
            if (!clientId.equals(tokenRequest.getClientId())) {
                // Double check to make sure that the client ID in the token request is the same as that in the authenticated client
                throw new InvalidClientException(String.format("Given client ID [%s] does not match the authenticated client", clientId));
            }
        }

        if (authenticatedClient != null) {
            oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
        }
        if (!hasText(tokenRequest.getGrantType())) {
            throw new InvalidRequestException("Missing grant type");
        }

        final OAuth2AccessToken token;

        if (isRefreshTokenRequest(parameters)) {
            // A refresh token has its own default scopes, so we should ignore any added by the factory here.
            tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
            token = refreshTokenGranter.grant(tokenRequest.getGrantType().toLowerCase(), tokenRequest);
        } else {
            token = tokenGranter.grant(tokenRequest.getGrantType().toLowerCase(), tokenRequest);
        }

        if (Objects.isNull(token)) {
            throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
        }

        return new ResponseEntity<>(token, HttpStatus.OK);
    }