1

我有一个使用 Spring Boot 完成的资源服务器。我正在使用 Spring Security 5.3 对前端交换数据进行身份验证和授权。我在 application.yml 中配置了一个授权服务器“issuer-uri”,它提供并验证 access_token (jwt)。

直到那里确定。授权服务器没有立即在access_token或id_token中提供我需要的每个用户信息的问题。使用 sub 声明和 access_token 我需要向端点发出请求以获取有关用户的更多额外数据。

我想知道如何在用户进行身份验证时请求获取该信息并将它们放入安全上下文中,以及已经获得的信息。这样,我可以在需要时在某些服务中获取该信息,而无需每次都向端点发出请求:

SecurityContextHolder.getContext().getAuthentication().getDetails()

这是我的 WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  private static final String CLAIM_ROLES = "role";
  private static final String AUTHORITY_PREFIX = "ROLE_";
  @Value("${sso.issuers_uri}")
  private String issuers;

  Map<String, AuthenticationManager> authenticationManagers = new HashMap<>();

  JwtIssuerAuthenticationManagerResolver authenticationManagerResolver =
        new JwtIssuerAuthenticationManagerResolver(authenticationManagers::get);


  @Override
  protected void configure(HttpSecurity http) throws Exception {
    String[] result = issuers.split(",");
    List<String> arrIssuers = Arrays.asList(result);

    arrIssuers.stream().forEach(issuer -> addManager(authenticationManagers, issuer));

    http
            .httpBasic().disable()
            .formLogin(AbstractHttpConfigurer::disable)
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeRequests(auth -> auth
                    .antMatchers(
                            "/*",
                            "/signin-oidc",
                            "/uri-login_unico",
                            "/assets/**","/views/**",
                            "index.html",
                            "/api/segmentos/listar_publicados",
                            "/api/modelos",
                            "/api/modelos/*"
                    ).permitAll()
                    .antMatchers(
                            "/api/admin/**"
                    ).hasRole("role.PGR.Admin")
                    .antMatchers(
                            "/api/govbr/**"
                    ).hasAnyAuthority("SCOPE_govbr_empresa")
                    .anyRequest().authenticated()
            ).oauth2ResourceServer(oauth2ResourceServer -> {
                oauth2ResourceServer.authenticationManagerResolver(this.authenticationManagerResolver);
            });
  }

  public void addManager(Map<String, AuthenticationManager> authenticationManagers, String issuer) {
    JwtAuthenticationProvider authenticationProvider = new JwtAuthenticationProvider(JwtDecoders.fromOidcIssuerLocation(issuer));
    authenticationProvider.setJwtAuthenticationConverter(getJwtAuthenticationConverter());
    authenticationManagers.put(issuer, authenticationProvider::authenticate);
  }

  private Converter<Jwt, AbstractAuthenticationToken> getJwtAuthenticationConverter() {
    JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
    
  jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(getJwtGrantedAuthoritiesConverter());
    return jwtAuthenticationConverter;
  }

  private Converter<Jwt, Collection<GrantedAuthority>> getJwtGrantedAuthoritiesConverter() {
    JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
    converter.setAuthorityPrefix(AUTHORITY_PREFIX);
    converter.setAuthoritiesClaimName(CLAIM_ROLES);
    return converter;
  }

}

我不知道是否需要自定义 AuthenticationManger,或者是否可以在经过身份验证后使用安全过滤器来执行此操作。如果有人可以帮助我,我真的很感激。咳咳!!!

4

0 回答 0