使用JWT的Spring OAuth - 仅在授权服务器中基于JWT执行授权

时间:2017-09-25 09:19:11

标签: spring spring-security jwt spring-oauth2

在我的系统中,我使用JWT令牌,以便可以仅基于JWT执行请求授权,无需调用数据库来获取角色等。我使用OAuth,我的服务是资源服务器,工作正常,我'我很满意。我遇到的问题是我的uaa-service,它既是授权服务器又是资源服务器。

我注意到当我向uaa-service发送请求时,我可以将@AuthenticatedPrincipal注入到我的控制器方法中,并且我可以访问所有用户字段,而不仅仅是那些存在于JWT中的字段。这意味着Spring以某种方式维护会话或者可能在后台从数据库中获取用户数据。以下是我的设置:

@Configuration
@EnableResourceServer
@Slf4j
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

@Override
public void configure(HttpSecurity http) throws Exception {
    log.info("Configuring resource server");
    http
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests()
            .antMatchers("/register").permitAll().anyRequest().authenticated();
}

@Autowired
public void setJwtAccessTokenConverter(JwtAccessTokenConverter jwtAccessTokenConverter) {
    jwtAccessTokenConverter.setAccessTokenConverter(bitcoinTokenConverter());
}

@Bean
DefaultAccessTokenConverter bitcoinTokenConverter() {
    return new CustomTokenConverter();
}

并且

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthServerConfig extends AuthorizationServerConfigurerAdapter {

@Autowired
private CustomUserDetailsService customUserDetailsService;

@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;

@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource(keystoreName), keystorePassword.toCharArray())
            .getKeyPair(keystoreAlias);
    converter.setKeyPair(keyPair);

    return converter;
}

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

@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
    return new DefaultAccessTokenConverter();
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
    tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));
    endpoints
            .authenticationManager(authenticationManager)
            .userDetailsService(customUserDetailsService)
            .tokenEnhancer(tokenEnhancerChain);
}

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private CustomUserDetailsService customUserDetailsService;

@Autowired
private ApplicationEventPublisher applicationEventPublisher;

@Bean
FilterRegistrationBean forwardedHeaderFilter() {
    FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
    filterRegBean.setFilter(new ForwardedHeaderFilter());
    filterRegBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegBean;
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            .authorizeRequests().antMatchers("/register").permitAll().anyRequest().authenticated();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    auth.authenticationEventPublisher(new DefaultAuthenticationEventPublisher(applicationEventPublisher));
}

我在哪里弄错了?在我的SecurityConfig.java中我有

auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());

这样可以通过从数据库中获取用户并验证密码来执行登录,但看起来它也可能导致传入请求不仅仅基于JWT处理。

0 个答案:

没有答案