Skip to content

Commit

Permalink
Merge pull request #273 from JiHongKim98/feature/actuator-and-s3
Browse files Browse the repository at this point in the history
스프링 엑츄에이터 추가
  • Loading branch information
JiHongKim98 authored Oct 3, 2024
2 parents 4eaf9a5 + 95eb0d5 commit e17cec8
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 26 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ repositories {
dependencies {
// Spring
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-validation'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
Expand Down Expand Up @@ -73,6 +74,9 @@ dependencies {

// RateLimit
implementation 'com.bucket4j:bucket4j_jdk17-lettuce:8.14.0'

// Prometheus
implementation 'io.micrometer:micrometer-registry-prometheus'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.example.daobe.auth.infrastructure.security;

import static com.example.daobe.auth.infrastructure.security.exception.SecurityExceptionType.INVALID_USER_INFO;

import com.example.daobe.auth.infrastructure.security.exception.SecurityException;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class BasicAuthenticationProvider implements AuthenticationProvider {

private static final String ROLE_PREFIX = "ROLE_";

private final SecurityProperties properties;

@Override
public Authentication authenticate(
Authentication authentication
) throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
List<SimpleGrantedAuthority> authorityList = extractAuthorityList(name, password);
return new UsernamePasswordAuthenticationToken(name, password, authorityList);
}

@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication);
}

private List<SimpleGrantedAuthority> extractAuthorityList(
String name,
String password
) throws AuthenticationException {
User securityUser = properties.getUser();
if (isMatchUser(name, password, securityUser)) {
throw new SecurityException(INVALID_USER_INFO);
}
return securityUser.getRoles().stream()
.map(value -> new SimpleGrantedAuthority(ROLE_PREFIX + value))
.collect(Collectors.toList());
}

private boolean isMatchUser(String name, String password, User securityUser) {
return !name.equals(securityUser.getName()) ||
!password.equals(securityUser.getPassword());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public enum SecurityExceptionType {
UNAUTHORIZED("인증 정보가 제공되지 않았습니다."),
INVALID_TOKEN("유효하지 않는 토큰입니다."),
EXPIRED_TOKEN("이미 만료된 토큰입니다."),
INVALID_USER_INFO("유효하지 않는 사용자 이름 혹은 비밀번호 입니다."),
;

private final String message;
Expand Down
52 changes: 27 additions & 25 deletions src/main/java/com/example/daobe/common/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.example.daobe.common.config;

import com.example.daobe.auth.infrastructure.security.BasicAuthenticationProvider;
import com.example.daobe.auth.infrastructure.security.JwtAuthenticationFilter;
import com.example.daobe.auth.infrastructure.security.JwtAuthenticationProvider;
import com.example.daobe.auth.infrastructure.security.handler.CustomAccessDeniedHandler;
import com.example.daobe.auth.infrastructure.security.handler.CustomAuthenticationEntryPoint;
import com.example.daobe.auth.infrastructure.security.oauth.CustomAuthorizationRequestRepository;
import com.example.daobe.auth.infrastructure.security.oauth.OAuthSuccessHandler;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
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.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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;
Expand All @@ -20,6 +22,7 @@
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationEntryPointFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
Expand All @@ -33,20 +36,23 @@ public class SecurityConfig {
private final OAuthSuccessHandler oAuthSuccessHandler;
private final CustomAccessDeniedHandler accessDeniedHandler;
private final JwtAuthenticationProvider jwtAuthenticationProvider;
private final BasicAuthenticationProvider basicAuthenticationProvider;
private final CustomAuthenticationEntryPoint authenticationEntryPoint;
private final CustomAuthorizationRequestRepository customAuthorizationRequestRepository;

@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration configuration
) throws Exception {
return configuration.getAuthenticationManager();
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(jwtAuthenticationProvider, basicAuthenticationProvider));
}

@Bean
public BasicAuthenticationFilter basicAuthenticationFilter(AuthenticationManager authenticationManager) {
return new BasicAuthenticationFilter(authenticationManager, authenticationEntryPoint);
}

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter(AuthenticationManager authenticationManager) {
RequestMatcher requestMatcher = generatedRequestMatcher();
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(requestMatcher);
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(generatedRequestMatcher());
filter.setAuthenticationManager(authenticationManager);
filter.setAuthenticationFailureHandler(
new AuthenticationEntryPointFailureHandler(authenticationEntryPoint)
Expand All @@ -57,6 +63,7 @@ public JwtAuthenticationFilter jwtAuthenticationFilter(AuthenticationManager aut
private RequestMatcher generatedRequestMatcher() {
return new NegatedRequestMatcher(
new OrRequestMatcher(
new AntPathRequestMatcher("/actuator/**"),
new AntPathRequestMatcher("/api/v1/health"),
new AntPathRequestMatcher("/api/v1/auth/reissue"),
new AntPathRequestMatcher("/oauth2/authorization/kakao"),
Expand All @@ -66,43 +73,38 @@ private RequestMatcher generatedRequestMatcher() {
}

@Bean
public SecurityFilterChain securityFilterChain(
public SecurityFilterChain securityFilterChainJwt(
HttpSecurity http,
AuthenticationManager authenticationManager
JwtAuthenticationFilter jwtAuthenticationFilter,
BasicAuthenticationFilter basicAuthenticationFilter
) throws Exception {
return http
.cors(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable)
.logout(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/**").hasRole("ADMIN")
.requestMatchers("/ws/init").permitAll()
.requestMatchers("/api/v1/health").permitAll()
.requestMatchers("/api/v1/auth/reissue").permitAll()
.requestMatchers("/oauth2/authorization/kakao").permitAll()
.requestMatchers("/ws/init").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfoEndpointConfig -> userInfoEndpointConfig
.userService(new DefaultOAuth2UserService())
)
.authorizationEndpoint(
authorizationEndpointConfig -> authorizationEndpointConfig.authorizationRequestRepository(
customAuthorizationRequestRepository))
.authorizationEndpoint(authorizationEndpointConfig -> authorizationEndpointConfig
.authorizationRequestRepository(customAuthorizationRequestRepository)
)
.successHandler(oAuthSuccessHandler)
)
.addFilterBefore(
jwtAuthenticationFilter(authenticationManager),
UsernamePasswordAuthenticationFilter.class
)
.exceptionHandling(handler -> handler
.accessDeniedHandler(accessDeniedHandler)
)
.authenticationProvider(jwtAuthenticationProvider)
.addFilterAt(basicAuthenticationFilter, BasicAuthenticationFilter.class)
.addFilterAt(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(handler -> handler.accessDeniedHandler(accessDeniedHandler))
.authenticationManager(authenticationManager())
.build();
}
}
10 changes: 10 additions & 0 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
management:
endpoints:
web:
exposure:
include: "prometheus,health"

spring:
jackson:
property-naming-strategy: SNAKE_CASE
Expand Down Expand Up @@ -50,6 +56,10 @@ spring:
open-in-view: false

security:
user:
name: admin
password: admin
roles: ADMIN
oauth2:
success-redirect: http://localhost:5173
client:
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/config

0 comments on commit e17cec8

Please sign in to comment.