在Spring Boot JWT Plus Oauth2中,TokenStore findTokensByClientId(clientId)返回空数组(我想要活动令牌)

时间:2019-04-22 09:10:20

标签: java spring-security oauth-2.0 jwt spring-security-oauth2

我用jwt和oauth2(在内存中)实现了spring boot。

这里的令牌位于内存而不是数据库中。

但是当我使用tokenStore.findTokensByClientId(clientId)时,在以下情况下它将返回空白数组

示例

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {


    static final String CLIEN_ID = "vishvas-client";
    static final String CLIENT_SECRET = "$2a$10$kfH4W.jyBuqvX5TLu.OfbOEUtScm4V9FEUDvGI8AWPaqObUOQ7HJ2"; // vishvas-secret
    static final String GRANT_TYPE_PASSWORD = "password";
    static final String AUTHORIZATION_CODE = "authorization_code";
    static final String REFRESH_TOKEN = "refresh_token";
    static final String IMPLICIT = "implicit";
    static final String SCOPE_READ = "read";
    static final String SCOPE_WRITE = "write";
    static final String TRUST = "trust";
    static final int ACCESS_TOKEN_VALIDITY_SECONDS = 12 * 60 * 60; // 12 hour
    static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 24 * 60 * 60; // 24 hour

    @Autowired
    private AuthenticationManager authenticationManager;

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("as466gf");
        return converter;
    }

    @Bean
    public TokenStore tokenStore() {
        //  return new InMemoryTokenStore();   // Success : working but same access token generated every time. i want different access tokens
        return new JwtTokenStore(accessTokenConverter()); // Error :  tokenStore.findTokensByClientId(clientId) returns blank

    }

    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {

        configurer.inMemory().withClient(CLIEN_ID).secret(CLIENT_SECRET)
                .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT)
                .scopes(SCOPE_READ, SCOPE_WRITE, TRUST).accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
                .refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter());
    }
}


@RestController
@RequestMapping("/api/tokens")
public class TokensEndpointController {

    @Autowired
    private TokenStore tokenStore;

    @CrossOrigin
    @SuppressWarnings({ "unchecked", "rawtypes", "deprecation" })
    @GetMapping
    public ResponseEntity<?> findAllActiveSessions(@RequestParam String clientId,
            HttpServletRequest httpServletRequest) {

        try {

            String username = httpServletRequest.getUserPrincipal().getName();

            Collection<OAuth2AccessToken> tokens = tokenStore.findTokensByClientId(clientId);
            List<String> tokenValues = tokens.stream().map(OAuth2AccessToken::getValue).collect(Collectors.toList());

            System.out.println("tokenValues : " + tokenValues); // Blank array

            return ResponseEntity.ok(new ResponseWrapperDTO(HttpServletResponse.SC_OK,
                    httpServletRequest.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString(),
                    "Tokens got successfully.", tokenValues));

        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity(
                    new ResponseErrorDTO(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                            MethodUtils.getApiPathFromHttpServletRequest(httpServletRequest), e.getMessage()),
                    HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

}

示例说明:

  1. tokenStore()方法中,如果我使用return new InMemoryTokenStore();,则可以使用api(http://localhost:8080/api/tokens?clientId=vishvas-client)成功获取所有令牌,但是每次生成相同的访问令牌

  2. tokenStore()方法中,如果我使用return new JwtTokenStore(accessTokenConverter());,则api(http://localhost:8080/api/tokens?clientId=vishvas-client)返回空数组。 (第二点的问题,无法获得令牌)

1 个答案:

答案 0 :(得分:1)

  1. 在第一个配置“ InMemoryTokenStore ”中:
    • 标准的oauth2令牌生成方法,意味着将为每个用户生成一个令牌,并将其存储(因此,当您向授权服务器请求客户端的令牌时,它将获取未生成的令牌),直到令牌到期,然后将生成另一个令牌
  

这就是为什么每次都获得相同的令牌的原因,但是当该令牌到期时,授权服务器将生成另一个令牌。

  1. 在第二个配置“ JwtTokenStore ”中:
    • 是标准的 oauth2 jwt令牌生成方法,意味着每次您请求令牌时,授权服务器都会为您生成令牌,并且不存储记忆中
    • 在这一点上,如果您正在使用JWT令牌,则服务器需要是无状态的,这意味着不需要令牌存储或用户信息存储,因为JWT令牌是自包含的,服务器不需要存储令牌或用户信息
  

这就是为什么您每次都会获得不同的令牌,但列表为空的原因

您可以在第162行link中检查 JwtTokenStore 类,您会发现默认情况下会给出一个空列表

因此,对于标准配置,您应该使用 JwtTokenStore