15 Aralık 2019 Pazar

SpringSecurity OAuth2 Resource Server OAuth2ResourceServerConfigurer Sınıfı - Client Credentials Grant

Giriş
Şu satırı dahil ederiz
import org.springframework.security.config.annotation.web.configurers.oauth2.server.
  resource.OAuth2ResourceServerConfigurer;
Resource Server ayarları içindir. Resource Server bir kaynağa erişmek istenirse doğrulama ve yetkilendirme ister. Bu sınıf ta bu işleri JWT token ile yapar

Maven
Örnek
Şu satırı dahil ederiz
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
Kullanım
Şöyle yaparız
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfiguration {

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .cors()
        .and()
      .authorizeRequests()
      .anyRequest()
      .authenticated()
        .and()
      .oauth2ResourceServer()
      .jwt();
    return http.build();
  }
}
bearerTokenResolver metodu - Örnek - jwt Decoder
Örnek
Elimizde şöyle bir kod olsun. Burada JWT Bearer Token olarak değil Custom Header içinde gönderiliyor.
@Configuration
@EnableWebSecurity
public class SecurityConfig {

  @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
  private String issuerUri;

  protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

  http.headers().httpStrictTransportSecurity().disable();

  http
    .csrf().disable()
    .sessionManagement()
    .and()
    .authorizeRequests() 
     // permit all requests to /customers/public/**
    .requestMatchers("/customers/public/**").permitAll() 
     // authenticate all requests to /customers/private/**
    .requestMatchers("/customers/private/**").authenticated() 
    .anyRequest().authenticated()
    .and()
    .oauth2ResourceServer()
    // added for custom bearer token
    .bearerTokenResolver(customBearerTokenResolver()) 
    .jwt().decoder(jwtDecoder());

    return http.build();
  }
}
Resolver şöyledir
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.util.StringUtils;

public class CustomBearerTokenResolver implements BearerTokenResolver {

  private String X_CUSTOM_HEADER = "x-custom-header";

  @Override
  public String resolve(HttpServletRequest request) {
    String customHeader = request.getHeader(X_CUSTOM_HEADER);
    System.out.println("customHeader: " + customHeader);
    if (StringUtils.hasText(customHeader)) {
      return customHeader;
    }
    return null;
  }
}
jwt metodu
Örnek
Şöyle yaparız.
@Override
public void configure(HttpSecurity http) throws Exception {
  http
    .authorizeRequests()
      .anyRequest().permitAll()
    .and()
      .oauth2Login()
    .and()
      .oauth2ResourceServer().jwt();
}
Örnek
Şöyle yaparız
@SpringBootApplication
public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @EnableGlobalMethodSecurity(prePostEnabled = true) public static class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .oauth2ResourceServer().jwt(); } } @RestController public class RequestCotroller { @PreAuthorize("hasAuthority('SCOPE_mod_custom')") @GetMapping("/") public String getMessage(Principal principal) { return "Welcome, " + principal.getName(); } } }
Örnek - JWT Decoder
Burada JWT Bearer Token olarak gönderiliyor. Elimizde şöyle bir kod olsun
@Configuration @EnableWebSecurity public class SecurityConfig { @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") private String issuerUri; protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.headers().httpStrictTransportSecurity().disable(); http .csrf().disable() .sessionManagement() .and() .authorizeRequests() // permit all requests to /customers/public/** .requestMatchers("/customers/public/**").permitAll() // authenticate all requests to /customers/private/** .requestMatchers("/customers/private/**").authenticated() .anyRequest().authenticated() .and() .oauth2ResourceServer() jwt().decoder(jwtDecoder()); return http.build(); } }
Şöyle yaparız
@Bean public JwtDecoder jwtDecoder() { JwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSetUri(issuerUri).build(); return new JwtDecoder() { @Override public Jwt decode(String token) throws JwtException { System.out.println("token: " + token); Jwt jwt = jwtDecoder.decode(token); System.out.println("jwt: " + jwt); return jwt; } }; }

jwt metodu - Customizer
Örnek
Şöyle yaparız
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .oauth2ResourceServer() .jwt(jwt -> jwt.jwtAuthenticationConverter( jwtAuthenticationConverter())); } Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter() { JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter(); jwtConverter.setJwtGrantedAuthoritiesConverter(new RealmRoleConverter()); return jwtConverter; } public class RealmRoleConverter implements Converter<Jwt, Collection<GrantedAuthority>> { @Override public Collection<GrantedAuthority> convert(Jwt jwt) { Map<String, List<String>> realmAccess = (Map<String, List<String>>) jwt.getClaims() .get("realm_access"); return realmAccess.get("roles").stream() .map(roleName -> "ROLE_" + roleName) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); } }
Açıklaması şöyle
In this converter, we extract the “realm_access” claims and then convert them to roles, using the ROLE_ as a prefix. Spring security requires this prefix to interpret them as roles.

Hiç yorum yok:

Yorum Gönder