Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package OneQ.OnSurvey.global.auth.application.strategy;

import OneQ.OnSurvey.domain.member.Member;
import jakarta.servlet.http.HttpServletRequest;

public interface AuthStrategy {
Member authenticate(HttpServletRequest request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package OneQ.OnSurvey.global.auth.application.strategy;

import OneQ.OnSurvey.domain.member.Member;
import OneQ.OnSurvey.domain.member.value.MemberStatus;
import OneQ.OnSurvey.domain.member.value.Role;
import jakarta.servlet.http.HttpServletRequest;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Slf4j
@Profile({"local", "docker-local"})
@Component
@NoArgsConstructor
public class LocalAuthStrategy implements AuthStrategy {

static {
log.info("===== LocalAuthStrategy authenticate called =====");
}

@Override
public Member authenticate(HttpServletRequest request) {
return Member.builder()
.id(1L)
.userKey(1234567890L)
.role(Role.ROLE_MEMBER)
.status(MemberStatus.ACTIVE)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package OneQ.OnSurvey.global.auth.application.strategy;

import OneQ.OnSurvey.domain.member.Member;
import OneQ.OnSurvey.domain.member.repository.MemberRepository;
import OneQ.OnSurvey.global.auth.application.AuthUseCase;
import OneQ.OnSurvey.global.infra.toss.common.dto.auth.LoginMeResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Component;

@Slf4j
@Profile("prod")
@Component
@RequiredArgsConstructor
public class TossAuthStrategy implements AuthStrategy {

private final AuthUseCase authUseCase;
private final MemberRepository memberRepository;

static {
log.info("===== ProdAuthStrategy authenticate called =====");
}

@Override
public Member authenticate(HttpServletRequest request) {
LoginMeResponse.Success me = authUseCase.authenticateWithToss(request);
return memberRepository.findMemberByUserKey(me.userKey())
.orElseThrow(() -> new BadCredentialsException("member not found"));
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package OneQ.OnSurvey.global.auth.filter;

import OneQ.OnSurvey.domain.member.Member;
import OneQ.OnSurvey.domain.member.repository.MemberRepository;
import OneQ.OnSurvey.domain.member.value.MemberStatus;
import OneQ.OnSurvey.global.auth.application.AuthUseCase;
import OneQ.OnSurvey.global.auth.application.strategy.AuthStrategy;
import OneQ.OnSurvey.global.auth.custom.CustomUserDetails;
import OneQ.OnSurvey.global.common.exception.CustomException;
import OneQ.OnSurvey.global.infra.toss.common.dto.auth.LoginMeResponse;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
Expand All @@ -26,10 +24,9 @@
@Component
@RequiredArgsConstructor
@Slf4j
public class TossAuthFilter extends OncePerRequestFilter {
public class AuthFilter extends OncePerRequestFilter {

private final AuthUseCase authUseCase;
private final MemberRepository memberRepository;
private final AuthStrategy authStrategy;
private final AuthenticationEntryPoint authenticationEntryPoint;

@Override
Expand Down Expand Up @@ -57,22 +54,13 @@ protected boolean shouldNotFilter(HttpServletRequest req) {
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
LoginMeResponse.Success me = authUseCase.authenticateWithToss(req);

Member member = memberRepository.findMemberByUserKey(me.userKey())
.orElseThrow(() -> new BadCredentialsException("member not found"));
Member member = authStrategy.authenticate(req);

if (!MemberStatus.isSameMemberStatus(member.getStatus(), MemberStatus.ACTIVE)) {
throw new BadCredentialsException("session expired");
}

CustomUserDetails principal = new CustomUserDetails(
Member.builder()
.id(member.getId())
.userKey(me.userKey())
.role(member.getRole())
.build()
);
CustomUserDetails principal = new CustomUserDetails(member);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(principal, null, principal.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package OneQ.OnSurvey.global.common.config;

import OneQ.OnSurvey.domain.member.repository.MemberRepository;
import OneQ.OnSurvey.global.auth.application.AuthUseCase;
import OneQ.OnSurvey.global.auth.filter.AuthFilter;
import OneQ.OnSurvey.global.auth.filter.ExactBasicHeaderFilter;
import OneQ.OnSurvey.global.auth.filter.TossAuthFilter;
import OneQ.OnSurvey.global.common.handler.CustomAccessDeniedHandler;
import OneQ.OnSurvey.global.common.handler.JWTAuthenticationEntryPoint;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -32,62 +30,54 @@ public class SecurityConfig {

private final JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final CustomAccessDeniedHandler customAccessDeniedHandler;
private final MemberRepository memberRepository;
private final AuthUseCase authUseCase;

private final String[] allowedUrls = {
"/",
"/swagger-ui/**",
"/v3/api-docs/**",
"/actuator/health",
"/auth/toss/login",
"/auth/reissue",
"/connect-out",
"/sentry-test/**",
"/toss/promotion/recheck-pending"
"/",
"/swagger-ui/**",
"/v3/api-docs/**",
"/actuator/health",
"/auth/toss/login",
"/auth/reissue",
"/connect-out",
"/sentry-test/**",
"/toss/promotion/recheck-pending"
};

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}

@Bean
public TossAuthFilter tossAuthFilter() {
return new TossAuthFilter(authUseCase, memberRepository, jwtAuthenticationEntryPoint);
}

@Bean @Order(2)
public SecurityFilterChain filterChain(HttpSecurity http, TossAuthFilter tossAuthFilter) throws Exception {
public SecurityFilterChain filterChain(HttpSecurity http, AuthFilter authFilter) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers(allowedUrls).permitAll()
.anyRequest().hasRole("MEMBER")
)
.addFilterBefore(tossAuthFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(e -> e
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(customAccessDeniedHandler));
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers(allowedUrls).permitAll()
.anyRequest().hasRole("MEMBER")
)
.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(e -> e
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(customAccessDeniedHandler));
return http.build();
}

@Bean @Order(1)
public SecurityFilterChain tossUnlinkChain(HttpSecurity http)
throws Exception {
public SecurityFilterChain tossUnlinkChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/connect-out")
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().permitAll())
.httpBasic(AbstractHttpConfigurer::disable)
.addFilterBefore(new ExactBasicHeaderFilter(expectedHeader), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(e -> e
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(customAccessDeniedHandler));
.securityMatcher("/connect-out")
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().permitAll())
.httpBasic(AbstractHttpConfigurer::disable)
.addFilterBefore(new ExactBasicHeaderFilter(expectedHeader), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(e -> e
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(customAccessDeniedHandler));
return http.build();
}
}
Expand Down
Loading