Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NO_JIRA] Jwt 토큰 관련 이슈 & Swagger authenticate 설정 #59

Merged
merged 2 commits into from
Jul 19, 2024
Merged
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
Expand Up @@ -19,6 +19,18 @@ public class SecurityConfig {

private final JwtTokenUtil jwtTokenUtil;

private static final String[] AUTH_WHITELIST = {
"/api/**",
"/swagger-ui/**",
"/api-docs",
"swagger-ui-custom.html",
"/v3/api-docs/**",
"/api-docs/**",
"/swagger-ui.html",
"/favicon.ico/**",
"/api/v1/members/**"
};

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
Expand All @@ -31,9 +43,10 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.authorizeHttpRequests(
authorize ->
authorize
// 테스트, 개발 중엔 모든 경로 오픈.
.requestMatchers("/**")
.permitAll())
.requestMatchers(AUTH_WHITELIST)
.permitAll()
.anyRequest()
.authenticated())
// UsernamePasswordAuthenticationFilter 필터 전에 jwt 필터가 먼저 동작하도록함.
.addFilterBefore(
new JwtAuthenticationFilter(jwtTokenUtil),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@

@ComponentScan(basePackages = {"org.depromeet.spot.application"})
@Configuration
@Import(value = {UsecaseConfig.class, JpaConfig.class, NcpConfig.class})
@Import(value = {UsecaseConfig.class, JpaConfig.class, NcpConfig.class, SwaggerConfig.class})
public class SpotApplicationConfig {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.depromeet.spot.application.common.config;

import java.util.List;

import jakarta.servlet.ServletContext;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.security.SecurityScheme.In;
import io.swagger.v3.oas.models.security.SecurityScheme.Type;
import io.swagger.v3.oas.models.servers.Server;
import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class SwaggerConfig {

@Bean
public OpenAPI openAPI(ServletContext servletContext) {
String contextPath = servletContext.getContextPath();
Server server = new Server().url(contextPath);
return new OpenAPI()
.servers(List.of(server))
.addSecurityItem(new SecurityRequirement().addList("accessToken"))
.components(authSetting())
.info(swaggerInfo());
}

private Info swaggerInfo() {
return new Info()
.version("v0.0.1")
.title("야구장 좌석 시야 서비스, SPOT API 문서")
.description("SPOT 서버의 API 문서입니다.");
}

private Components authSetting() {
return new Components()
.addSecuritySchemes(
"accessToken",
new SecurityScheme()
.type(Type.HTTP)
.scheme("Bearer")
.bearerFormat("JWT")
.in(In.HEADER)
.name("Authorization"));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.depromeet.spot.application.common.jwt;

import java.io.IOException;
import java.util.List;
import java.util.Arrays;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
Expand All @@ -26,31 +26,29 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final JwtTokenUtil jwtTokenUtil;

private static final String[] AUTH_WHITELIST = {
"/swagger-ui",
"/api-docs",
"swagger-ui-custom.html",
"/v3/api-docs",
"/api-docs",
"/swagger-ui.html",
"/favicon.ico",
"/api/v1/members"
};

@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {

List<String> list =
List.of(
// swagger-ui와 v3/api-docs는 스웨거를 제외하기 위해 등록.
// 혹시나 스웨거 자원 사용 에러 발생 시 아래 두 가지 추가 필요함.
// Swagger UI에서 사용하는 외부 라ㅇ이브러리 제공 엔드포인트 : "/webjars/**"
// Swagger UI에서 사용하는 리소스 제공 엔드포인트 : "/swagger-resources/**"
// 로그인, 회원가입은 제외
"/swagger-ui", "/v3/api-docs", "/api/v1/members", "/kakao/", "/api/v1/");

// 현재 URL 이 LIST 안에 포함되있는걸로 시작하는가?
boolean flag = list.stream().anyMatch(url -> request.getRequestURI().startsWith(url));

if (flag) {
String header = request.getHeader(HttpHeaders.AUTHORIZATION);
final String requestURI = request.getRequestURI();
if (Arrays.stream(AUTH_WHITELIST).anyMatch(requestURI::startsWith)) {
filterChain.doFilter(request, response);
return;
}

String header = request.getHeader(HttpHeaders.AUTHORIZATION);
log.info("JwtAuthenticationFilter header : {}", header);

// header가 null이거나 빈 문자열이면 안됨.
if (header != null && !header.equalsIgnoreCase("")) {
if (header.startsWith("Bearer")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.depromeet.spot.application.common.jwt;

import java.security.Key;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -41,15 +44,20 @@ public String getJWTToken(Member member) {
}

public String generateToken(Long memberId, MemberRole memberRole) {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime expiredAtDateTime = currentDateTime.plusYears(1);

ZonedDateTime zonedCurrent = expiredAtDateTime.atZone(ZoneId.systemDefault());
ZonedDateTime zonedExpire = expiredAtDateTime.atZone(ZoneId.systemDefault());
Date current = Date.from(zonedCurrent.toInstant());
Date expiredAt = Date.from(zonedExpire.toInstant());

return Jwts.builder()
.setHeader(createHeader())
.setClaims(createClaims(memberRole))
.setSubject(memberId.toString())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(
new Date(
System.currentTimeMillis()
+ 1000 * 60 * 60 * 24 * 30 * 12L)) // 토큰 만료 시간
.setIssuedAt(current)
.setExpiration(expiredAt)
.signWith(SignatureAlgorithm.HS256, SECRETKEY.getBytes())
.compact();
}
Expand Down
Loading