【问题标题】:Oauth2 Server returns "Access Token" instead of Jwt TokenOauth2 服务器返回“访问令牌”而不是 Jwt 令牌
【发布时间】:2020-05-25 05:58:07
【问题描述】:

按照可以找到 here 的教程替换现有的 oauth 配置,该配置为 jwt 令牌返回“访问令牌”。当我运行应用程序并查询服务器进行身份验证时,它似乎返回“access_token”而不是 JWT 令牌。本教程使用的是 spring boot,我们的应用程序是非 boot 普通 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;
    }

}

//CustomTokenEnhancer 类

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;
    }
}

//CustomAccessTokenConverter类

@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {

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

【问题讨论】:

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


    【解决方案1】:

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

    下面是它返回的payload

    eyJ1c2VyX25hbWUiOiJ3aWxsbGFkaXNsYXciLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjQ2OGI3MzFmLTUxMzgtNDZhYi04MTU3LTU1MmZlMjM1MzY2ZSIsImNsaWVudF9pZCI6ImNsaWVudGFwcCIsInNjb3BlIjpbInJlYWRfd3JpdGUiXSwib3JnYW5pemF0aW9uIjoid2lsbGxhZGlzbGF3QmdNSiJ9
    

    这是用base64解码后的样子

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

    您现在可以在标头值Authorization: Bearer &lt;JWT Token&gt; 中使用以下 JWT 令牌并访问任何受保护的资源。

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ3aWxsbGFkaXNsYXciLCJhdXRob3JpdGllcyI6WyJST0xFX0FETUlOIl0sImp0aSI6IjQ2OGI3MzFmLTUxMzgtNDZhYi04MTU3LTU1MmZlMjM1MzY2ZSIsImNsaWVudF9pZCI6ImNsaWVudGFwcCIsInNjb3BlIjpbInJlYWRfd3JpdGUiXSwib3JnYW5pemF0aW9uIjoid2lsbGxhZGlzbGF3QmdNSiJ9.fUhFeUDuhm8f2V7CuURsZWKoAKjNZixk5rUa0Jyzov8
    

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

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 1970-01-01
      • 2019-12-08
      • 2017-03-08
      • 2019-10-23
      • 2018-10-17
      • 2015-10-23
      • 1970-01-01
      • 2022-10-23
      相关资源
      最近更新 更多