You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
3.9 KiB
Java
79 lines
3.9 KiB
Java
package com.yau.digitalrmb.security.config;
|
|
|
|
import com.nimbusds.jose.jwk.source.ImmutableSecret;
|
|
import com.nimbusds.jose.proc.SecurityContext;
|
|
import com.yau.digitalrmb.shared.api.ApiResponse;
|
|
import com.yau.digitalrmb.shared.api.ErrorCode;
|
|
import com.yau.digitalrmb.shared.web.TraceIdFilter;
|
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
import org.springframework.context.annotation.Bean;
|
|
import org.springframework.context.annotation.Configuration;
|
|
import org.springframework.http.MediaType;
|
|
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.AbstractHttpConfigurer;
|
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
|
|
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.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.UUID;
|
|
|
|
@Configuration
|
|
@EnableWebSecurity
|
|
@EnableConfigurationProperties(SecurityProperties.class)
|
|
public class SecurityConfig {
|
|
@Bean
|
|
public PasswordEncoder passwordEncoder() {
|
|
return new BCryptPasswordEncoder();
|
|
}
|
|
|
|
@Bean
|
|
public JwtEncoder jwtEncoder(SecurityProperties properties) {
|
|
return new NimbusJwtEncoder(new ImmutableSecret<SecurityContext>(secretKey(properties)));
|
|
}
|
|
|
|
@Bean
|
|
public JwtDecoder jwtDecoder(SecurityProperties properties) {
|
|
return NimbusJwtDecoder.withSecretKey(secretKey(properties)).macAlgorithm(MacAlgorithm.HS256).build();
|
|
}
|
|
|
|
@Bean
|
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
return http.csrf(AbstractHttpConfigurer::disable)
|
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
|
.authorizeHttpRequests(authorize -> authorize
|
|
.requestMatchers("/actuator/health", "/api/v1/auth/login", "/api/v1/auth/sso",
|
|
"/api/v1/auth/cas/**", "/api/v1/auth/session/exchange",
|
|
"/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html")
|
|
.permitAll()
|
|
.anyRequest().authenticated())
|
|
.oauth2ResourceServer(resourceServer -> resourceServer.jwt(jwt -> { }))
|
|
.exceptionHandling(exceptions -> exceptions
|
|
.authenticationEntryPoint((request, response, exception) -> writeError(response, ErrorCode.UNAUTHORIZED, 401))
|
|
.accessDeniedHandler((request, response, exception) -> writeError(response, ErrorCode.FORBIDDEN, 403)))
|
|
.build();
|
|
}
|
|
|
|
private static SecretKeySpec secretKey(SecurityProperties properties) {
|
|
return new SecretKeySpec(properties.getJwt().getSecret().getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
|
}
|
|
|
|
private static void writeError(jakarta.servlet.http.HttpServletResponse response, ErrorCode code, int status)
|
|
throws java.io.IOException {
|
|
response.setStatus(status);
|
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|
String traceId = response.getHeader(TraceIdFilter.HEADER_NAME);
|
|
if (traceId == null) traceId = UUID.randomUUID().toString();
|
|
response.getWriter().write("{\"code\":\"" + code.name() + "\",\"message\":\"" + code.name()
|
|
+ "\",\"data\":null,\"traceId\":\"" + traceId + "\"}");
|
|
}
|
|
}
|