Oauth2 服务器 returns "Access Token" 而不是 Jwt 令牌

Oauth2 Server returns "Access Token" instead of Jwt Token

按照可以找到的教程 here 替换现有的 oauth 配置,returns 一个 'access token' 一个 jwt 令牌。当我 运行 应用程序并查询服务器进行身份验证时,它似乎返回 "access_token" 而不是 JWT 令牌。本教程使用 spring 引导,而我们的应用程序是非引导普通 spring mvc,因此不确定是否涉及任何其他步骤?

服务器响应: {"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ3aWxsbGFkaXNsYXciLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjQ2OGI3MzFmLTUxMzgtNDZhYi04MTU3LTU1MmZlMjM1MzY2ZSIsImNsaWVudF9pZCI6ImNsaWVudGFwcCIsInNjb3BlIjpbInJlYWRfd3JpdGUiXSwib3JnYW5pemF0aW9uIjoid2lsbGxhZGlzbGF3QmdNSiJ9.fUhFeUDuhm8f2V7CuURsZWKoAKjNZixk5rUa0Jyzov8","refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbsUiOiJ3aWxsbGFkaXNsYXciLCJzY29wZSI6WyJyZWFkX3dyaXRlIl0sIm9yZ2FuaXphdGlvbiI6IndpbGxsYWRpc2xhd0JnTUoiLCJhdGkiOiI0NjhiNzMxZi01MTM4LTQ2YWItODE1Ny01NTJmZTIzNTM2NmUiLCJleHAiOjE1ODM4NDA5NTgsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iXSwianRpIjoiOGIxNGE3NjMtZmMwMy00MDQ4LWJkNGQtYjZiMTUyOGU2NTE4IiwiY2xpZW50X2lkIjoiY2xpZW50YXBwIn0.UhkxVsgM4CnZeRRKGyyCbiyqb2M0BmL56sHbsxt5Opk","idToken":null,"tokenEndpoint":"http://localhost:8080/oauth/token","scopes":["read_write"],"expiration":null}

//OAuth 服务器

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {
    final String clientId;
    final String clientSecret;
    final String redirectUri;
    final String grantType;
    final String scope;
  ....

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    DataSource dataSource;

    @Autowired
    RepositoryUserDetailsService userDetailsService;

    @Autowired
    private CustomAccessTokenConverter customAccessTokenConverter;


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(
                Arrays.asList(tokenEnhancer(), accessTokenConverter()));

        endpoints.tokenStore(tokenStore())
                .tokenEnhancer(tokenEnhancerChain)
                .authenticationManager(authenticationManager);
    }

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
    }


    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder);
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

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

    @Bean
    @Primary
    public ResourceServerTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }


    @Bean
    protected AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(dataSource);
    }



    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.
                jdbc(dataSource)
                .withClient(clientId)
                .secret(passwordEncoder.encode(clientSecret))
                .autoApprove(true)
                .redirectUris(redirectUri)
                .authorizedGrantTypes("password", "refresh_token")
                .accessTokenValiditySeconds(0)
                .scopes(scope);
    }
}

//资源服务器

@Configuration
@EnableResourceServer
public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
    @Autowired
    private CustomAccessTokenConverter customAccessTokenConverter;
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/register/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin().loginPage("/signin/**")
                .and()
                .requestMatchers()
                .antMatchers("/api/**");

    }

    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        config.tokenServices(tokenServices());
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

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

    @Bean
    @Primary
    public ResourceServerTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }

}

//CustomTokenEnhancerClass

public class CustomTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(
            OAuth2AccessToken accessToken,
            OAuth2Authentication authentication) {
        Map<String, Object> additionalInfo = new HashMap<>();
        additionalInfo.put(
                "organization", authentication.getName() + randomAlphabetic(4));
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(
                additionalInfo);
        return accessToken;
    }
}

//CustomAccessTokenConverterClass

@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {

    @Override
    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
        OAuth2Authentication authentication =
                super.extractAuthentication(claims);
        authentication.setDetails(claims);
        return authentication;
    }
}

您的 Spring Security OAuth2 配置工作正常,并且已经 return 使用 JWT 令牌。

以下是它的payload returns

eyJ1c2VyX25hbWUiOiJ3aWxsbGFkaXNsYXciLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjQ2OGI3MzFmLTUxMzgtNDZhYi04MTU3LTU1MmZlMjM1MzY2ZSIsImNsaWVudF9pZCI6ImNsaWVudGFwcCIsInNjb3BlIjpbInJlYWRfd3JpdGUiXSwib3JnYW5pemF0aW9uIjoid2lsbGxhZGlzbGF3QmdNSiJ9

这是用base64解码后的样子

{"user_name":"willladislaw","authorities":["ROLE_ADMIN"],"jti":"468b731f-5138-46ab-8157-552fe235366e","client_id":"clientapp","scope":["read_write"],"organization":"willladislawBgMJ"}

您现在可以在 header 值 Authorization: Bearer <JWT Token> 中使用以下 JWT 令牌并访问任何受保护的资源。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ3aWxsbGFkaXNsYXciLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjQ2OGI3MzFmLTUxMzgtNDZhYi04MTU3LTU1MmZlMjM1MzY2ZSIsImNsaWVudF9pZCI6ImNsaWVudGFwcCIsInNjb3BlIjpbInJlYWRfd3JpdGUiXSwib3JnYW5pemF0aW9uIjoid2lsbGxhZGlzbGF3QmdNSiJ9.fUhFeUDuhm8f2V7CuURsZWKoAKjNZixk5rUa0Jyzov8

你所做的是你已经要求 Spring Security OAuth2 生成一个 JWT 令牌,其中包含关于登录用户的自包含信息,并将其替换为它使用的基于标准 UUID accessToken默认。仅仅因为您使用的是 JWT 令牌并不意味着您会在登录时从 oauth/token 端点获得 jwtToken return。详细了解 JWT