Spring OAuth2 - 更改默认签名算法

Posted

技术标签:

【中文标题】Spring OAuth2 - 更改默认签名算法【英文标题】:Spring OAuth2 - Change default signing algorithm 【发布时间】:2018-07-06 15:10:30 【问题描述】:

我是 Spring Security 的新手,我需要在我的应用程序中实现 JWT 身份验证。所以我在春季网站上通过 OAuth2 指南制作了这段代码。它工作得很好,但默认情况下使用 SHA256 签名算法。你能告诉我如何更改我的代码,使用 SHA512 或其他算法吗?谢谢。

这是我的实现:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
    @Value("$security.signing-key")
    private String signingKey;

    @Value("$security.encoding-strength")
    private Integer encodingStrength;

    @Value("$security.security-realm")
    private String securityRealm;

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception 
        return super.authenticationManager();
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .httpBasic()
                .realmName(securityRealm)
                .and()
                .csrf()
                .disable();

    

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() 
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signingKey);
        return converter;
    

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

    @Bean
    @Primary
    //Making this primary to avoid any accidental duplication with another token service instance of the same name
    public DefaultTokenServices tokenServices() 
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    

授权服务器:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter 
    @Value("$security.jwt.client-id")
    private String clientId;

    @Value("$security.jwt.client-secret")
    private String clientSecret;

    @Value("$security.jwt.grant-type")
    private String grantType;

    @Value("$security.jwt.scope-read")
    private String scopeRead;

    @Value("$security.jwt.scope-write")
    private String scopeWrite = "write";

    @Value("$security.jwt.resource-ids")
    private String resourceIds;

    @Value("$security.jwt.expiration")
    private int expiration;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception 
        configurer
                .inMemory()
                .withClient(clientId)
                .secret(clientSecret)
                .authorizedGrantTypes(grantType)
                .scopes(scopeRead, scopeWrite)
                .resourceIds(resourceIds)
                .accessTokenValiditySeconds(expiration);
    

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
        endpoints.tokenStore(tokenStore)
                .accessTokenConverter(accessTokenConverter)
                .tokenEnhancer(enhancerChain)
                .authenticationManager(authenticationManager);
    

资源服务器:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter 
    @Autowired
    private ResourceServerTokenServices tokenServices;

    @Value("$security.jwt.resource-ids")
    private String resourceIds;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception 
        resources.resourceId(resourceIds).tokenServices(tokenServices);
    

    @Override
    public void configure(HttpSecurity http) throws Exception 
        http
                .requestMatchers()
                .and()
                .authorizeRequests()
                .antMatchers("/actuator/**", "/api-docs/**").permitAll()
                .antMatchers("/springjwt/**" ).authenticated();
    

【问题讨论】:

【参考方案1】:

从 Spring Security OAuth2 2.0.12 版本开始可以设置签名者,见Unable to configure the algorithm used for signing and verifying:

desmondrawls 于 2016 年 10 月 7 日发表评论

我们需要 RsaSigner 和 RsaVerifier 类来使用 sha512 而不是 sha256。因为 JwtAccessTokenConverter 使用它们的默认算法 sha256 实例化这些类,所以配置算法的唯一方法似乎是在重写受包保护的 RsaKeyHelper 时扩展 JwtAccessTokenConverter、RsaSigner 和 RsaVerifier。我们不想维护那么多 spring-security 类。我们还能怎么做呢?是否可以重写 JwtAccessTokenConverter 以便更轻松地配置算法?

JwtAccessTokenConverter:

public void setVerifier(org.springframework.security.jwt.crypto.sign.SignatureVerifier verifier)

无条件设置验证者(验证者密钥随后被忽略)。

[...]

public void setSigner(org.springframework.security.jwt.crypto.sign.Signer signer)

无条件设置要使用的签名者(如果需要)。然后忽略签名者密钥。

【讨论】:

以上是关于Spring OAuth2 - 更改默认签名算法的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security OAuth2 更改 JSON 错误响应格式

Oauth2 Spring 中的更改响应

Spring OAuth2刷新令牌刷新访问令牌后更改

Spring Boot + Azure Active Directory 签名的 JWT 被拒绝:需要另一个算法,或者找不到匹配的密钥

单点登录JWT与Spring Security OAuth

Spring JWT 签名验证失败