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

标签 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>

我必须更改标准 token 请求:

原始 token 请求:

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

迫切的 token 请求

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

最佳答案

它不会像这样工作,因为您的自定义端点类不会加载到 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);
    }

关于spring-boot - Spring Oauth2 - 自定义TokenEndpoint从@RequestParam到@RequestBody,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50717442/

相关文章:

java - 在哪里可以找到 Websphere eXtreme Scale 的 Maven 依赖项?

grails - Grails 3-Spring Security OAuth2提供程序-自定义安全提供程序被忽略

spring - 如何在 POST 中发送 ClientId 和 ClientSecret,而不是在带有 ClientCredentialsAccessTokenProvider 的 header 中

java - 如何对 Spring 存储库进行单元测试

java - 我如何确定是否使用 Spring jpa 插入或更新记录

java - 在 servlet 多部分发布期间无法访问 Spring Security 信息

java - 如何在 Spring Boot WebFlux 中使用 GET 请求注销

java - Spring 注入(inject)接口(interface)实现给出 Nullpointer

java - Spring Oauth2 单点登录 : Use Authority granted by AuthorizationServer

java - @ControllerAdvice 不返回 json 响应