Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
| web:framework:spring:oauth2 [2024/04/16 13:11] – [Services et authentification] jcheron | web:framework:spring:oauth2 [2024/04/16 13:58] (Version actuelle) – jcheron | ||
|---|---|---|---|
| Ligne 227: | Ligne 227: | ||
| </ | </ | ||
| + | ==== Configuration ==== | ||
| + | |||
| + | <sxh kotlin; | ||
| + | import com.nimbusds.jose.jwk.JWK | ||
| + | import com.nimbusds.jose.jwk.JWKSet | ||
| + | import com.nimbusds.jose.jwk.RSAKey | ||
| + | import com.nimbusds.jose.jwk.source.ImmutableJWKSet | ||
| + | import com.nimbusds.jose.jwk.source.JWKSource | ||
| + | import com.nimbusds.jose.proc.SecurityContext | ||
| + | import fr.zerp.api.security.JpaUserDetailsService | ||
| + | import fr.zerp.api.security.RsaKeyConfigProperties | ||
| + | import org.slf4j.Logger | ||
| + | import org.slf4j.LoggerFactory | ||
| + | import org.springframework.beans.factory.annotation.Autowired | ||
| + | import org.springframework.context.annotation.Bean | ||
| + | import org.springframework.context.annotation.Configuration | ||
| + | import org.springframework.security.authentication.AuthenticationManager | ||
| + | import org.springframework.security.authentication.ProviderManager | ||
| + | import org.springframework.security.authentication.dao.DaoAuthenticationProvider | ||
| + | import org.springframework.security.config.Customizer | ||
| + | import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity | ||
| + | import org.springframework.security.config.annotation.web.builders.HttpSecurity | ||
| + | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity | ||
| + | import org.springframework.security.config.annotation.web.configurers.CorsConfigurer | ||
| + | import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer | ||
| + | import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer | ||
| + | import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer | ||
| + | import org.springframework.security.config.http.SessionCreationPolicy | ||
| + | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder | ||
| + | import org.springframework.security.crypto.password.PasswordEncoder | ||
| + | import org.springframework.security.oauth2.jwt.JwtDecoder | ||
| + | import org.springframework.security.oauth2.jwt.JwtEncoder | ||
| + | import org.springframework.security.oauth2.jwt.NimbusJwtDecoder | ||
| + | import org.springframework.security.oauth2.jwt.NimbusJwtEncoder | ||
| + | import org.springframework.security.web.SecurityFilterChain | ||
| + | import org.springframework.web.servlet.handler.HandlerMappingIntrospector | ||
| + | |||
| + | |||
| + | @Configuration | ||
| + | @EnableWebSecurity | ||
| + | @EnableMethodSecurity | ||
| + | class SecurityConfig { | ||
| + | |||
| + | @Autowired | ||
| + | lateinit var rsaKeyConfigProperties: | ||
| + | |||
| + | @Autowired | ||
| + | lateinit var userDetailsService: | ||
| + | |||
| + | |||
| + | @Bean | ||
| + | fun authManager(): | ||
| + | val authProvider = DaoAuthenticationProvider() | ||
| + | authProvider.setUserDetailsService(userDetailsService) | ||
| + | authProvider.setPasswordEncoder(passwordEncoder()) | ||
| + | return ProviderManager(authProvider) | ||
| + | } | ||
| + | |||
| + | |||
| + | @Bean | ||
| + | @Throws(Exception:: | ||
| + | fun filterChain(http: | ||
| + | return http | ||
| + | .csrf { csrf: CsrfConfigurer< | ||
| + | csrf.disable() | ||
| + | } | ||
| + | .cors { cors: CorsConfigurer< | ||
| + | .authorizeHttpRequests { auth -> | ||
| + | auth.requestMatchers("/ | ||
| + | auth.requestMatchers("/ | ||
| + | auth.requestMatchers("/ | ||
| + | auth.anyRequest().authenticated() | ||
| + | }.headers { headers -> | ||
| + | headers.frameOptions { it.sameOrigin() } | ||
| + | } | ||
| + | .sessionManagement { s: SessionManagementConfigurer< | ||
| + | s.sessionCreationPolicy( | ||
| + | SessionCreationPolicy.STATELESS | ||
| + | ) | ||
| + | } | ||
| + | .oauth2ResourceServer { oauth2: OAuth2ResourceServerConfigurer< | ||
| + | oauth2.jwt { jwt -> | ||
| + | jwt.decoder( | ||
| + | jwtDecoder() | ||
| + | ) | ||
| + | } | ||
| + | } | ||
| + | .userDetailsService(userDetailsService) | ||
| + | .httpBasic(Customizer.withDefaults()) | ||
| + | .build() | ||
| + | } | ||
| + | |||
| + | @Bean | ||
| + | fun jwtDecoder(): | ||
| + | return NimbusJwtDecoder.withPublicKey(rsaKeyConfigProperties.publicKey).build() | ||
| + | } | ||
| + | |||
| + | @Bean | ||
| + | fun jwtEncoder(): | ||
| + | val jwk: JWK = | ||
| + | RSAKey.Builder(rsaKeyConfigProperties.publicKey).privateKey(rsaKeyConfigProperties.privateKey).build() | ||
| + | |||
| + | val jwks: JWKSource< | ||
| + | return NimbusJwtEncoder(jwks) | ||
| + | } | ||
| + | |||
| + | @Bean | ||
| + | fun passwordEncoder(): | ||
| + | return BCryptPasswordEncoder() | ||
| + | } | ||
| + | |||
| + | companion object { | ||
| + | private val log: Logger = LoggerFactory.getLogger(SecurityConfig:: | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | ==== Authentification ==== | ||
| + | === DTO === | ||
| + | |||
| + | <sxh kotlin> | ||
| + | class AuthDTO { | ||
| + | @JvmRecord | ||
| + | data class LoginRequest(val username: String, val password: String) | ||
| + | |||
| + | @JvmRecord | ||
| + | data class Response(val message: String, val token: String) | ||
| + | } | ||
| + | </ | ||
| + | === Controller === | ||
| + | |||
| + | <sxh kotlin> | ||
| + | @RestController | ||
| + | @RequestMapping("/ | ||
| + | @Validated | ||
| + | class AuthController { | ||
| + | |||
| + | @Autowired | ||
| + | lateinit var authService: | ||
| + | |||
| + | @Autowired | ||
| + | lateinit var authenticationManager: | ||
| + | |||
| + | @PostMapping("/ | ||
| + | @Throws(IllegalAccessException:: | ||
| + | fun login(@RequestBody userLogin: AuthDTO.LoginRequest): | ||
| + | val authentication: | ||
| + | authenticationManager | ||
| + | .authenticate( | ||
| + | UsernamePasswordAuthenticationToken( | ||
| + | userLogin.username, | ||
| + | userLogin.password | ||
| + | ) | ||
| + | ) | ||
| + | SecurityContextHolder.getContext().authentication = authentication | ||
| + | val userDetails = authentication.getPrincipal() as AuthUser | ||
| + | log.info(" | ||
| + | val token = authService.generateToken(authentication) | ||
| + | val response: AuthDTO.Response = AuthDTO.Response(" | ||
| + | return ResponseEntity.ok< | ||
| + | } | ||
| + | |||
| + | companion object { | ||
| + | private val log: Logger = LoggerFactory.getLogger(AuthController:: | ||
| + | } | ||
| + | } | ||
| + | </ | ||