[회원 관리 기능 추가] 회원 등록 및 로그인 API 구현, JWT 토큰 발급 및 검증 필터 추가. Member 관련 DTO, Entity, Mapper, Repository, Service 구현으로 회원 관리 기능을 강화하고, Swagger 설정을 통해 API 문서화 개선.

This commit is contained in:
2025-08-20 16:22:11 +09:00
parent bfb87b8e33
commit 0dc32f2b39
22 changed files with 151 additions and 115 deletions

View File

@@ -26,6 +26,7 @@ repositories {
dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// PostgreSQL JDBC
runtimeOnly 'org.postgresql:postgresql'
implementation 'org.springframework.boot:spring-boot-starter-web'
@@ -45,6 +46,8 @@ dependencies {
// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5'
// lombok
compileOnly 'org.projectlombok:lombok'

View File

@@ -1,18 +1,17 @@
package com.bio.bio_backend.domain.user.member.controller;
package com.bio.bio_backend.domain.base.member.controller;
import com.bio.bio_backend.global.dto.ApiResponseDto;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
import com.bio.bio_backend.domain.user.member.service.MemberService;
import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
import com.bio.bio_backend.domain.base.member.dto.CreateMemberRequestDto;
import com.bio.bio_backend.domain.base.member.dto.CreateMemberResponseDto;
import com.bio.bio_backend.domain.base.member.service.MemberService;
import com.bio.bio_backend.domain.base.member.mapper.MemberMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import io.swagger.v3.oas.annotations.Operation;
@@ -32,7 +31,6 @@ public class MemberController {
private final MemberService memberService;
private final MemberMapper memberMapper;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
@LogExecution("회원 등록")
@Operation(summary = "회원 등록", description = "새로운 회원을 등록합니다.")
@@ -51,6 +49,28 @@ public class MemberController {
return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
}
@LogExecution("로그아웃")
@Operation(summary = "로그아웃", description = "사용자 로그아웃을 처리합니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "로그아웃 성공"),
@ApiResponse(responseCode = "401", description = "인증 실패", content = @Content(schema = @Schema(implementation = ApiResponseDto.class)))
})
@PostMapping("/logout")
public ResponseEntity<ApiResponseDto<Void>> logout(@RequestHeader("Authorization") String authorization) {
try {
// Authorization 헤더에서 토큰 추출
String token = authorization.replace("Bearer ", "");
// Refresh Token 삭제 (실제로는 JWT 블랙리스트나 DB에서 삭제)
// memberService.deleteRefreshToken(userId);
return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS));
} catch (Exception e) {
log.error("로그아웃 처리 중 오류 발생: {}", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponseDto.fail(ApiResponseCode.COMMON_INTERNAL_SERVER_ERROR));
}
}
// @PostMapping("/member/list")
// public ResponseEntity<List<ResponseMember>> getMemberList(@RequestBody(required = false) Map<String, String> params) {

View File

@@ -1,4 +1,4 @@
package com.bio.bio_backend.domain.user.member.dto;
package com.bio.bio_backend.domain.base.member.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;

View File

@@ -1,6 +1,6 @@
package com.bio.bio_backend.domain.user.member.dto;
package com.bio.bio_backend.domain.base.member.dto;
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
import com.bio.bio_backend.domain.base.member.enums.MemberRole;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.bio.bio_backend.domain.user.member.dto;
package com.bio.bio_backend.domain.base.member.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;

View File

@@ -1,4 +1,4 @@
package com.bio.bio_backend.domain.user.member.dto;
package com.bio.bio_backend.domain.base.member.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;

View File

@@ -1,6 +1,6 @@
package com.bio.bio_backend.domain.user.member.dto;
package com.bio.bio_backend.domain.base.member.dto;
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
import com.bio.bio_backend.domain.base.member.enums.MemberRole;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

View File

@@ -1,6 +1,6 @@
package com.bio.bio_backend.domain.user.member.entity;
package com.bio.bio_backend.domain.base.member.entity;
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
import com.bio.bio_backend.domain.base.member.enums.MemberRole;
import com.bio.bio_backend.global.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;

View File

@@ -1,4 +1,4 @@
package com.bio.bio_backend.domain.user.member.enums;
package com.bio.bio_backend.domain.base.member.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

View File

@@ -1,10 +1,9 @@
package com.bio.bio_backend.domain.user.member.mapper;
package com.bio.bio_backend.domain.base.member.mapper;
import com.bio.bio_backend.domain.user.member.dto.CreateMemberRequestDto;
import com.bio.bio_backend.domain.user.member.dto.CreateMemberResponseDto;
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
import com.bio.bio_backend.domain.user.member.entity.Member;
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
import com.bio.bio_backend.domain.base.member.dto.CreateMemberRequestDto;
import com.bio.bio_backend.domain.base.member.dto.CreateMemberResponseDto;
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
import com.bio.bio_backend.domain.base.member.entity.Member;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@@ -20,7 +19,7 @@ public interface MemberMapper {
* 기본값 설정: role = MemberRole.MEMBER, useFlag = true
*/
@Mapping(target = "oid", ignore = true)
@Mapping(target = "role", expression = "java(com.bio.bio_backend.domain.user.member.enums.MemberRole.getDefault())")
@Mapping(target = "role", expression = "java(com.bio.bio_backend.domain.base.member.enums.MemberRole.getDefault())")
@Mapping(target = "useFlag", constant = "true")
@Mapping(target = "refreshToken", ignore = true)
@Mapping(target = "lastLoginAt", ignore = true)

View File

@@ -1,9 +1,9 @@
package com.bio.bio_backend.domain.user.member.repository;
package com.bio.bio_backend.domain.base.member.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bio.bio_backend.domain.user.member.entity.Member;
import com.bio.bio_backend.domain.base.member.entity.Member;
import java.util.Optional;
@Repository

View File

@@ -1,6 +1,6 @@
package com.bio.bio_backend.domain.user.member.repository;
package com.bio.bio_backend.domain.base.member.repository;
import com.bio.bio_backend.domain.user.member.entity.Member;
import com.bio.bio_backend.domain.base.member.entity.Member;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

View File

@@ -1,10 +1,9 @@
package com.bio.bio_backend.domain.user.member.repository;
package com.bio.bio_backend.domain.base.member.repository;
import com.bio.bio_backend.domain.user.member.entity.Member;
import com.bio.bio_backend.domain.user.member.entity.QMember;
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
import com.bio.bio_backend.domain.base.member.entity.Member;
import com.bio.bio_backend.domain.base.member.entity.QMember;
import com.bio.bio_backend.domain.base.member.enums.MemberRole;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;

View File

@@ -1,4 +1,4 @@
package com.bio.bio_backend.domain.user.member.service;
package com.bio.bio_backend.domain.base.member.service;
import java.util.List;
import java.util.Map;
@@ -6,7 +6,7 @@ import java.util.Map;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
public interface MemberService extends UserDetailsService {

View File

@@ -1,10 +1,10 @@
package com.bio.bio_backend.domain.user.member.service;
package com.bio.bio_backend.domain.base.member.service;
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
import com.bio.bio_backend.domain.user.member.entity.Member;
import com.bio.bio_backend.domain.user.member.enums.MemberRole;
import com.bio.bio_backend.domain.user.member.mapper.MemberMapper;
import com.bio.bio_backend.domain.user.member.repository.MemberRepository;
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
import com.bio.bio_backend.domain.base.member.entity.Member;
import com.bio.bio_backend.domain.base.member.enums.MemberRole;
import com.bio.bio_backend.domain.base.member.mapper.MemberMapper;
import com.bio.bio_backend.domain.base.member.repository.MemberRepository;
import com.bio.bio_backend.global.exception.ApiException;
import com.bio.bio_backend.global.constants.ApiResponseCode;
import lombok.RequiredArgsConstructor;

View File

@@ -1,9 +1,16 @@
package com.bio.bio_backend.global.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class AppConfig {
@@ -11,4 +18,21 @@ public class AppConfig {
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// JavaTimeModule 등록
JavaTimeModule javaTimeModule = new JavaTimeModule();
// LocalDateTime 직렬화/역직렬화 설정
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
mapper.registerModule(javaTimeModule);
return mapper;
}
}

View File

@@ -29,9 +29,6 @@ public class CustomAuthenticationFailureHandler implements AuthenticationFailure
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
log.info("exception : " + exception.toString());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
response.setStatus(HttpStatus.UNAUTHORIZED.value());

View File

@@ -7,10 +7,10 @@ import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.bio.bio_backend.global.dto.ApiResponseDto;
import com.bio.bio_backend.domain.user.member.dto.LoginRequestDto;
import com.bio.bio_backend.domain.user.member.dto.LoginResponseDto;
import com.bio.bio_backend.domain.user.member.dto.MemberDto;
import com.bio.bio_backend.domain.user.member.service.MemberService;
import com.bio.bio_backend.domain.base.member.dto.LoginRequestDto;
import com.bio.bio_backend.domain.base.member.dto.LoginResponseDto;
import com.bio.bio_backend.domain.base.member.dto.MemberDto;
import com.bio.bio_backend.domain.base.member.service.MemberService;
import com.bio.bio_backend.global.constants.ApiResponseCode;
import com.bio.bio_backend.global.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
@@ -35,12 +35,13 @@ import java.util.Objects;
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public class JwtTokenIssuanceFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final MemberService memberService;
private final JwtUtils jwtUtils;
private final Environment env;
private final ObjectMapper objectMapper;
// 사용자 login 인증 처리
@SneakyThrows
@@ -93,7 +94,6 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
// JWT 토큰 전달
response.setHeader("Authorization", "Bearer " + accessToken);
// response.addCookie(refreshTokenCookie);
response.addHeader("Set-Cookie",
String.format("%s=%s; HttpOnly; Secure; Path=/; Max-Age=%d; SameSite=None",
refreshTokenCookie.getName(),
@@ -112,8 +112,10 @@ public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilte
// login 성공 메시지 전송
response.setStatus(HttpStatus.OK.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getWriter(),
ApiResponseDto.success(ApiResponseCode.LOGIN_SUCCESSFUL, memberData));
response.setContentType(MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8");
objectMapper.writeValue(
response.getWriter(),
ApiResponseDto.success(ApiResponseCode.LOGIN_SUCCESSFUL, memberData)
);
}
}

View File

@@ -13,13 +13,12 @@ import org.springframework.web.filter.OncePerRequestFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.bio.bio_backend.global.dto.ApiResponseDto;
import com.bio.bio_backend.domain.user.member.service.MemberService;
import com.bio.bio_backend.domain.base.member.service.MemberService;
import com.bio.bio_backend.global.constants.ApiResponseCode;
import com.bio.bio_backend.global.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
@@ -27,18 +26,12 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
@Slf4j
public class JwtTokenFilter extends OncePerRequestFilter {
public class JwtTokenValidationFilter extends OncePerRequestFilter {
private final JwtUtils jwtUtils;
private final MemberService memberService;
private final Environment env;
private final UriAllowFilter uriAllowFilter;
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return uriAllowFilter.authExceptionAllow(request);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
@@ -53,41 +46,53 @@ public class JwtTokenFilter extends OncePerRequestFilter {
}
try {
// 토큰 유효성 검사
try {
if (jwtUtils.validateAccessToken(accessToken)) {
String username = jwtUtils.extractUsername(accessToken);
UserDetails userDetails = memberService.loadUserByUsername(username);
// Access Token 유효성 검사
if (jwtUtils.validateAccessToken(accessToken)) {
String username = jwtUtils.extractUsername(accessToken);
UserDetails userDetails = memberService.loadUserByUsername(username);
if (userDetails != null) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
return;
}
if (userDetails != null) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
return;
}
} catch (ExpiredJwtException ignored) {
// Access Token이 만료된 경우에만 ignored >> Refresh Token 검증 수행
}
// Refresh Token 유효성 검사
// Access Token이 유효하지 않거나 만료된 경우 Refresh Token 검증
if (refreshToken != null && jwtUtils.validateRefreshToken(refreshToken)) {
String username = jwtUtils.extractUsername(refreshToken);
String role = (String) jwtUtils.extractAllClaims(refreshToken).get("role");
// 새로운 Access Token 생성
String newAccessToken = jwtUtils.generateToken(username, role,
Long.parseLong(Objects.requireNonNull(env.getProperty("token.expiration_time_access"))));
// 새로운 Access Token을 응답 헤더에 설정
response.setHeader("Authorization", "Bearer " + newAccessToken);
// 인증 정보 설정
UserDetails userDetails = memberService.loadUserByUsername(username);
if (userDetails != null) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
return;
} else {
sendJsonResponse(response, ApiResponseDto.fail(ApiResponseCode.ALL_TOKEN_INVALID, null));
sendJsonResponse(response, ApiResponseDto.fail(ApiResponseCode.ALL_TOKEN_INVALID));
return;
}
} catch (Exception e) {
request.setAttribute("exception", e);
sendJsonResponse(response, ApiResponseDto.fail(ApiResponseCode.COMMON_INTERNAL_SERVER_ERROR));
return;
}
filterChain.doFilter(request, response);
}
private void sendJsonResponse(HttpServletResponse response, ApiResponseDto<?> apiResponse) throws IOException {

View File

@@ -8,21 +8,18 @@ import org.springframework.security.config.annotation.authentication.builders.Au
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.CorsFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.Filter;
//import com.bio.bio_backend.domain.common.service.AccessLogService;
import com.bio.bio_backend.domain.user.member.service.MemberService;
import com.bio.bio_backend.domain.base.member.service.MemberService;
import com.bio.bio_backend.global.exception.CustomAuthenticationFailureHandler;
import com.bio.bio_backend.global.exception.JwtAccessDeniedHandler;
import com.bio.bio_backend.global.exception.JwtAuthenticationEntryPoint;
//import com.bio.bio_backend.global.filter.HttpLoggingFilter;
import com.bio.bio_backend.global.utils.HttpUtils;
import com.bio.bio_backend.global.utils.JwtUtils;
import lombok.RequiredArgsConstructor;
@@ -34,26 +31,20 @@ public class WebSecurity {
private final MemberService memberService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final JwtUtils jwtUtils;
// private final AccessLogService accessLogService;
private final CorsFilter corsFilter;
private final ObjectMapper objectMapper;
private final HttpUtils httpUtils;
private final Environment env;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final UriAllowFilter uriAllowFilter;
private JwtAuthenticationFilter getJwtAuthenticationFilter(AuthenticationManager authenticationManager) throws Exception {
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(authenticationManager, memberService, jwtUtils, env);
private JwtTokenIssuanceFilter getJwtTokenIssuanceFilter(AuthenticationManager authenticationManager) throws Exception {
JwtTokenIssuanceFilter filter = new JwtTokenIssuanceFilter(authenticationManager, memberService, jwtUtils, env, objectMapper);
filter.setFilterProcessesUrl("/login"); // 로그인 EndPoint
filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler(objectMapper));
return filter;
}
private Filter getJwtTokenFilter() {
return new JwtTokenFilter(jwtUtils, memberService, env, uriAllowFilter);
private Filter getJwtTokenValidationFilter() {
return new JwtTokenValidationFilter(jwtUtils, memberService, env);
}
@Bean
@@ -69,13 +60,15 @@ public class WebSecurity {
http.csrf(AbstractHttpConfigurer::disable) //csrf 비활성화
.authorizeHttpRequests(request -> //request 허용 설정
request
.anyRequest().permitAll() // 모든 요청 허용
// .requestMatchers("/ws/**").permitAll()
// .requestMatchers("/admin/**", "/join").hasAnyAuthority(MemberConstants.ROLE_ADMIN)
// .requestMatchers("/member/**").hasAnyAuthority(MemberConstants.ROLE_MEMBER)
// .anyRequest().authenticated()
.requestMatchers("/api/auth/**").permitAll() // 인증 관련 엔드포인트 허용
.requestMatchers("/swagger-ui/**", "/api-docs/**").permitAll() // Swagger 허용
.requestMatchers("/ws/**").permitAll() // WebSocket 허용
.anyRequest().authenticated() // 나머지 요청은 인증 필요
)
.authenticationManager(authenticationManager)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션 사용 안함
)
.logout(AbstractHttpConfigurer::disable);
// 예외 처리 핸들링
@@ -85,16 +78,11 @@ public class WebSecurity {
.accessDeniedHandler(jwtAccessDeniedHandler)
);
// http
// .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
// .addFilterBefore(new HttpLoggingFilter(accessLogService, httpUtils), UsernamePasswordAuthenticationFilter.class)
// .addFilterBefore(getJwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class)
// .addFilterBefore(getJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
// .sessionManagement(httpSecuritySessionManagementConfigurer -> //Session 사용 X
// httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http
// 1단계: JWT 토큰 발급 필터 (로그인 요청 처리 및 토큰 발급)
.addFilterBefore(getJwtTokenIssuanceFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class)
// 2단계: JWT 토큰 검증 필터 (모든 요청에 대해 토큰 유효성 검증)
.addFilterBefore(getJwtTokenValidationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}

View File

@@ -6,7 +6,7 @@ import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import com.bio.bio_backend.domain.user.member.service.MemberService;
import com.bio.bio_backend.domain.base.member.service.MemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

View File

@@ -95,4 +95,3 @@ springdoc.swagger-ui.doc-expansion=none
springdoc.swagger-ui.disable-swagger-default-url=true
springdoc.default-produces-media-type=application/json
springdoc.default-consumes-media-type=application/json