【问题标题】:Spring Security 5 populating authorities based on JWT claims基于 JWT 声明的 Spring Security 5 填充权限
【发布时间】:2020-04-10 06:36:37
【问题描述】:

正如我所见,Spring Security OAuth2.x 项目已移至 Spring Security 5.2.x。我尝试以新的方式实现授权和资源服务器。除了一件事 - @PreAuthorize 注释外,一切都正常工作。当我尝试将其与标准 @PreAuthorize("hasRole('ROLE_USER')") 一起使用时,我总是被禁止。我看到的是Principal 类型为org.springframework.security.oauth2.jwt.Jwt 的对象无法解析权限,我不知道为什么。

org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken@44915f5f: Principal: org.springframework.security.oauth2.jwt.Jwt@2cfdbd3; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffa64e: RemoteIpAddress: 172.19.0.1; SessionId: null; Granted Authorities: SCOPE_read, SCOPE_write

并在将其转换为Jwt后声明

{user_name=user, scope=["read","write"], exp=2019-12-18T13:19:29Z, iat=2019-12-18T13:19:28Z, authorities=["ROLE_USER","READ_ONLY"], client_id=sampleClientId}

安全服务器配置

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

  @Autowired
  private DataSource dataSource;

  @Autowired
  private AuthenticationManager authenticationManager;

  @Bean
  public KeyPair keyPair() {
    ClassPathResource ksFile = new ClassPathResource("mytest.jks");
    KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(ksFile, "mypass".toCharArray());
    return keyStoreKeyFactory.getKeyPair("mytest");
  }

  @Bean
  public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setKeyPair(keyPair());
    return converter;
  }

  @Bean
  public JWKSet jwkSet() {
    RSAKey key = new Builder((RSAPublicKey) keyPair().getPublic()).build();
    return new JWKSet(key);
  }

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

  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.jdbc(dataSource);
  }

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    endpoints.tokenStore(tokenStore())
        .accessTokenConverter(accessTokenConverter())
        .authenticationManager(authenticationManager);
  }

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

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  private UserDetailsService userDetailsService;

  public SecurityConfiguration(UserDetailsService userDetailsService) {
    this.userDetailsService = userDetailsService;
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .mvcMatchers("/.well-known/jwks.json")
            .permitAll()
            .anyRequest()
            .authenticated();
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

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

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
  }
}

资源服务器配置

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt();
    }
}

也许有人有类似的问题?

【问题讨论】:

    标签: java spring spring-security oauth spring-security-oauth2


    【解决方案1】:

    默认情况下,资源服务器根据"scope" 声明填充权限。
    如果Jwt 包含名称为"scope""scp" 的声明,则Spring Security 将使用该声明中的值通过在每个值前面加上"SCOPE_" 来构造权限。

    在您的示例中,声明之一是scope=["read","write"]
    这意味着权限列表将由"SCOPE_read""SCOPE_write" 组成。

    您可以通过在安全配置中提供自定义身份验证转换器来修改默认权限映射行为。

    http
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .oauth2ResourceServer()
            .jwt()
                .jwtAuthenticationConverter(getJwtAuthenticationConverter());
    

    然后在您的getJwtAuthenticationConverter 实现中,您可以配置Jwt 如何映射到权限列表。

    Converter<Jwt, AbstractAuthenticationToken> getJwtAuthenticationConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(jwt -> {
            // custom logic
        });
        return converter;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-09
      • 1970-01-01
      • 2020-12-18
      • 2019-06-27
      • 2021-04-13
      • 2013-07-07
      • 2011-08-11
      • 2021-04-28
      • 1970-01-01
      相关资源
      最近更新 更多