Spring Boot - 使用 JWT、OAuth 以及单独的资源和身份验证服务器

标签 spring spring-security oauth jwt spring-security-oauth2

我正在尝试构建一个使用 JWT token 和 OAuth2 协议(protocol)的 Spring 应用程序。多亏了this tutorial,我可以运行身份验证服务器.但是,我正在努力让资源服务器正常运行。关注文章,感谢对 prior question 的回复,这是我目前的尝试:

资源服务器的安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${security.signing-key}")
    private String signingKey;

    @Value("${security.encoding-strength}")
    private Integer clientID;

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

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifierKey(signingKey);
        return converter;
    }

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

    @Bean ResourceServerTokenServices tokenService() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        OAuth2AuthenticationManager authManager = new OAuth2AuthenticationManager();
        authManager.setTokenServices(tokenService());
        return authManager;
    }

}

资源服务器配置:
@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("/**").authenticated();
}

}

授权服务器的安全配置(来自注释教程):
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig 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 ShaPasswordEncoder(encodingStrength));
    }

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

现在,当我尝试向资源服务器发出请求时,我收到如下错误:
{"error":"invalid_token","error_description":"Invalid access token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidGVzdGp3dHJlc291cmNlaWQiXSwidXNlcl9uYW1lIjoiam9obi5kb2UiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiZXh wIjoxNTE1MTE3NTU4LCJhdXRob3JpdGllcyI6WyJTVEFOREFSRF"}
我有几个问题:
  • 据我了解,这个问题通常与 token 商店有关。使用 JwtTokenStore 时如何处理分离服务器?
  • 其次,目前,我的 Resource 应用程序依赖于对 key 的访问。根据我对 JWT 和 0Auth 规范的理解,这不是必需的。相反,我应该能够将验证委托(delegate)给身份验证服务器本身。从 Spring 文档中,我认为以下属性可能适用 security.oauth2.resource.token-info-uri=http://localhost:8080/oauth/check_token .但是,如果我尝试不依赖资源服务器的 key ,那么我在设置 ResourceServerTokenService 时会遇到困难。该服务需要一个 token 存储,JWTTokenStore 使用一个 JwtAccessTokenConverter,并且转换器使用一个 key (删除 key 会导致我之前遇到的相同的 invalid token 错误)。

  • 我真的很难找到展示如何分离身份验证和资源服务器的文章。任何意见,将不胜感激。

    编辑:
    实际上,资源服务器的代码现在无法编译并显示以下消息:
    Caused by: java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key

    最佳答案

    我尝试了spring oauth,但遇到了同样的错误:

    Caused by: java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key
    

    我的错误是我的公共(public)证书是:
    -----BEGIN PUBLIC KEY-----
    tadadada
    -----END PUBLIC KEY-----
    -----BEGIN CERTIFICATE-----
    tadadada
    -----END CERTIFICATE-----
    

    这是不允许的。删除证书,只需让此文件中的公钥:
    -----BEGIN PUBLIC KEY-----
    tadadada
    -----END PUBLIC KEY-----
    

    并且启动错误将消失。

    对于你的第二个问题,这就是我的理解:
  • 身份验证服务器为您提供加密 token (使用私钥加密),其中包含您用户的所有权限。
  • 资源服务器使用公钥解密 token ,并假设 token 中包含的权限为 TRUE。

  • 希望这有帮助。

    关于Spring Boot - 使用 JWT、OAuth 以及单独的资源和身份验证服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48098186/

    相关文章:

    java - 如何防止在事务提交时保存到 Hibernate 中的数据库?

    eclipse - 使用 Maven、Tomcat/Glassfish、Archetype 的高效开发周期?

    java - Spring 启动 WebMvcTest : How to test controller method with Authentication object parameter?

    grails - Spring Security 3.0.3-如果在插件或子插件中定义YML安全配置将不起作用

    php - 我应该使用什么范围(google login with hybridauth/oauth)

    asp.net - oAuth ASP.NET 成员(member)提供商

    spring - 如何在 Java 配置中使用 delegatingFilterproxy?

    Spring Security - 自定义过滤器

    java -/api-url 在 Spring Boot Security 中有一个空的过滤器列表

    Android 开发 - 回调 URL 无效... (0_o)