Skip to content
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
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,19 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
implementation 'org.springframework.boot:spring-boot-starter-validation'

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
Comment on lines +36 to +39

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

JWT 라이브러리 버전 확인 필요

JJWT 0.11.5 버전이 사용되고 있는데, 최신 버전과 보안 취약점 여부를 확인해야 합니다.


🌐 Web query:

What is the latest version of io.jsonwebtoken jjwt library and are there any security vulnerabilities in version 0.11.5?

💡 Result:

The latest version of the io.jsonwebtoken (JJWT) library is 0.12.6. (javadoc.io)

Regarding version 0.11.5, there are no direct vulnerabilities reported for this version in Snyk's vulnerability database. (security.snyk.io)

However, it's important to note that version 0.11.5 is outdated, and the latest version, 0.12.6, includes several updates and fixes. (github.com)

To ensure your application benefits from the latest security patches and features, it's recommended to upgrade to version 0.12.6.

Citations:


JWT 라이브러리 버전 업그레이드 권고

현재 io.jsonwebtoken:jjwt 0.11.5에는 알려진 취약점은 없으나, 최신 버전인 0.12.6 에 보안 패치와 기능 개선이 포함되어 있습니다. 안정성과 최신 기능 활용을 위해 의존성을 다음과 같이 업데이트하시기 바랍니다.

· 대상 파일: build.gradle (36–39줄)
· 변경 전:

implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly    'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly    'io.jsonwebtoken:jjwt-jackson:0.11.5'

· 제안하는 변경:

- implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
- runtimeOnly    'io.jsonwebtoken:jjwt-impl:0.11.5'
- runtimeOnly    'io.jsonwebtoken:jjwt-jackson:0.11.5'
+ implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
+ runtimeOnly    'io.jsonwebtoken:jjwt-impl:0.12.6'
+ runtimeOnly    'io.jsonwebtoken:jjwt-jackson:0.12.6'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
🤖 Prompt for AI Agents
In build.gradle between lines 36 and 39, the JWT library dependencies are using
version 0.11.5, which is outdated. Update all three dependencies 'jjwt-api',
'jjwt-impl', and 'jjwt-jackson' to version 0.12.6 to include the latest security
patches and feature improvements. Replace the version numbers in the
implementation and runtimeOnly lines accordingly.


runtimeOnly 'com.mysql:mysql-connector-j'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'


testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testCompileOnly 'org.projectlombok:lombok'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
Expand Down
48 changes: 48 additions & 0 deletions src/main/java/com/wayble/server/common/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.wayble.server.common.config;

import com.wayble.server.common.config.security.jwt.JwtAuthenticationFilter;
import com.wayble.server.common.config.security.jwt.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@RequiredArgsConstructor
@EnableMethodSecurity
public class SecurityConfig {

private final JwtTokenProvider jwtProvider;

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers(
"/api/v1/users/signup",
"/api/v1/users/login",
"/swagger-ui/**",
"/v3/api-docs/**"
).permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(new JwtAuthenticationFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class);

return http.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.wayble.server.common.config.security;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {

private String secret;
private long accessExp;


public String getSecret() {
return secret;
}

public long getAccessExp() {
return accessExp;
}

public void setSecret(String secret) {
this.secret = secret;
}

public void setAccessExp(long accessExp) {
this.accessExp = accessExp;
}
}
Comment on lines +6 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

JWT 설정 검증 및 보안 강화 필요

현재 구현에서 다음 사항들이 개선되어야 합니다:

  1. 비밀키 강도 검증 부족: JWT 비밀키의 최소 길이나 강도에 대한 검증이 없습니다.
  2. 기본값 부재: 설정이 누락될 경우를 대비한 기본값이 없습니다.
  3. 민감한 정보 노출 위험: 비밀키가 로그에 노출될 수 있습니다.

다음과 같이 개선하는 것을 권장합니다:

@Component
@ConfigurationProperties(prefix = "jwt")
+@Validated
public class JwtProperties {

+    @NotBlank(message = "JWT secret key cannot be blank")
+    @Size(min = 32, message = "JWT secret key must be at least 32 characters")
    private String secret;
+    
+    @Positive(message = "Access token expiration must be positive")
    private long accessExp;

+    @PostConstruct
+    public void validateSecretKey() {
+        if (secret.getBytes().length < 32) {
+            throw new IllegalArgumentException("JWT secret key must be at least 256 bits (32 bytes)");
+        }
+    }

    // getters and setters...
+    
+    @Override
+    public String toString() {
+        return "JwtProperties{accessExp=" + accessExp + ", secret=[PROTECTED]}";
+    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
private String secret;
private long accessExp;
public String getSecret() {
return secret;
}
public long getAccessExp() {
return accessExp;
}
public void setSecret(String secret) {
this.secret = secret;
}
public void setAccessExp(long accessExp) {
this.accessExp = accessExp;
}
}
@Component
@ConfigurationProperties(prefix = "jwt")
@Validated
public class JwtProperties {
@NotBlank(message = "JWT secret key cannot be blank")
@Size(min = 32, message = "JWT secret key must be at least 32 characters")
private String secret;
@Positive(message = "Access token expiration must be positive")
private long accessExp;
@PostConstruct
public void validateSecretKey() {
if (secret.getBytes().length < 32) {
throw new IllegalArgumentException("JWT secret key must be at least 256 bits (32 bytes)");
}
}
public String getSecret() {
return secret;
}
public long getAccessExp() {
return accessExp;
}
public void setSecret(String secret) {
this.secret = secret;
}
public void setAccessExp(long accessExp) {
this.accessExp = accessExp;
}
@Override
public String toString() {
return "JwtProperties{accessExp=" + accessExp + ", secret=[PROTECTED]}";
}
}
🤖 Prompt for AI Agents
In src/main/java/com/wayble/server/common/config/security/JwtProperties.java
lines 6 to 29, add validation logic to ensure the JWT secret key meets a minimum
length or strength requirement to enhance security. Provide sensible default
values for secret and accessExp fields to handle missing configuration
gracefully. Also, avoid exposing the secret key in logs or error messages by
removing or masking it wherever it might be logged.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.wayble.server.common.config.security.jwt;

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.List;

public class JwtAuthentication extends AbstractAuthenticationToken {
private final String email;

public JwtAuthentication(String email) {
super(List.of(new SimpleGrantedAuthority("ROLE_USER")));
this.email = email;
setAuthenticated(true);
}

@Override public Object getCredentials() { return ""; }
@Override public Object getPrincipal() { return email; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.wayble.server.common.config.security.jwt;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final JwtTokenProvider jwtProvider;

@Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws ServletException, IOException {

String header = req.getHeader("Authorization");

if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);

if (jwtProvider.validateToken(token)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

토큰 인증에 실패하면 사용자의 refreshToken을 바탕으로 accessToken을 재발급하는 것으로 알고 있습니다! 그런데 현재 코드에는 refreshToken 관련 로직이나 refreshToken Repository가 없어서 accessToken 만료 시에 문제가 생길 것 같아요...!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이것도 refreshToken 발급 관련 구현할때 로직 추가하겠습니다~!

String email = jwtProvider.getEmail(token);
var authentication = new JwtAuthentication(email);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
Comment on lines +23 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

토큰 무효화 시 SecurityContext 정리가 필요합니다.

토큰이 유효하지 않거나 검증에 실패한 경우, 기존 SecurityContext를 명시적으로 정리하는 것이 보안상 좋습니다.

 if (header != null && header.startsWith("Bearer ")) {
     String token = header.substring(7);
     
     if (jwtProvider.validateToken(token)) {
         String email = jwtProvider.getEmail(token);
         var authentication = new JwtAuthentication(email);
         SecurityContextHolder.getContext().setAuthentication(authentication);
+    } else {
+        SecurityContextHolder.clearContext();
     }
+} else {
+    SecurityContextHolder.clearContext();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
String header = req.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
if (jwtProvider.validateToken(token)) {
String email = jwtProvider.getEmail(token);
var authentication = new JwtAuthentication(email);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
String header = req.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
String token = header.substring(7);
if (jwtProvider.validateToken(token)) {
String email = jwtProvider.getEmail(token);
var authentication = new JwtAuthentication(email);
SecurityContextHolder.getContext().setAuthentication(authentication);
} else {
SecurityContextHolder.clearContext();
}
} else {
SecurityContextHolder.clearContext();
}
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/common/config/security/jwt/JwtAuthenticationFilter.java
around lines 23 to 33, the SecurityContext is not cleared when the JWT token is
invalid or fails validation. To fix this, explicitly clear the SecurityContext
by calling SecurityContextHolder.clearContext() in the else branch or after the
token validation check fails, ensuring no stale authentication remains.


chain.doFilter(req, res);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.wayble.server.common.config.security.jwt;

import com.wayble.server.common.config.security.JwtProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;

@Component
@RequiredArgsConstructor
public class JwtTokenProvider {
private final JwtProperties jwtProperties;

private Key getSigningKey() {
return Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes());
}
Comment on lines +17 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

서명 키 생성 성능 개선이 필요합니다.

매번 새로운 키를 생성하는 것은 비효율적입니다. 키를 캐싱하여 성능을 향상시키세요.

@Component
@RequiredArgsConstructor
public class JwtTokenProvider {
    private final JwtProperties jwtProperties;
+   private Key signingKey;

-   private Key getSigningKey() {
-       return Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes());
-   }
+   private Key getSigningKey() {
+       if (signingKey == null) {
+           signingKey = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes());
+       }
+       return signingKey;
+   }
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java
around lines 17 to 19, the getSigningKey method creates a new signing key on
every call, which is inefficient. To improve performance, modify the class to
generate the signing key once, cache it in a private final field, and return the
cached key in getSigningKey instead of recreating it each time.


public String generateToken(String email, String role) {
return Jwts.builder()
.setSubject(email)
.claim("role", role)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + jwtProperties.getAccessExp()))
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}

public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}

public String getEmail(String token) {
return Jwts.parserBuilder().setSigningKey(getSigningKey()).build()
.parseClaimsJws(token).getBody().getSubject();
}
Comment on lines +40 to +43

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

보안 취약점: 토큰 검증 없이 파싱하고 있습니다.

getEmail() 메서드에서 토큰 검증 없이 바로 파싱하는 것은 보안상 위험합니다. 토큰 유효성을 먼저 검증해야 합니다.

public String getEmail(String token) {
+   if (!validateToken(token)) {
+       throw new IllegalArgumentException("Invalid token");
+   }
    return Jwts.parserBuilder().setSigningKey(getSigningKey()).build()
            .parseClaimsJws(token).getBody().getSubject();
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public String getEmail(String token) {
return Jwts.parserBuilder().setSigningKey(getSigningKey()).build()
.parseClaimsJws(token).getBody().getSubject();
}
public String getEmail(String token) {
if (!validateToken(token)) {
throw new IllegalArgumentException("Invalid token");
}
return Jwts.parserBuilder().setSigningKey(getSigningKey()).build()
.parseClaimsJws(token).getBody().getSubject();
}
🤖 Prompt for AI Agents
In
src/main/java/com/wayble/server/common/config/security/jwt/JwtTokenProvider.java
around lines 40 to 43, the getEmail() method parses the JWT token without
verifying its validity first, which is a security risk. Modify the method to
first validate the token's signature and expiration by calling a token
validation method before extracting the email. Ensure that if the token is
invalid, the method handles it appropriately, such as throwing an exception or
returning null.

}
57 changes: 44 additions & 13 deletions src/main/java/com/wayble/server/user/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@
package com.wayble.server.user.controller;

import com.wayble.server.common.response.CommonResponse;
import com.wayble.server.user.dto.UserLoginRequestDto;
import com.wayble.server.user.dto.UserRegisterRequestDto;
import com.wayble.server.user.dto.token.TokenResponseDto;
import com.wayble.server.user.service.UserService;
import com.wayble.server.user.service.auth.AuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
@RequestMapping("/users")
@Validated
public class UserController {

private final UserService userService;
private final AuthService authService;

// 참고용 컨트롤러(지우셔도 돼요)
@GetMapping("/hello")
public CommonResponse<String> hello() {
return CommonResponse.success("hello");
@PostMapping("/signup")
@Operation(
summary = "유저 회원가입",
description = "신규 유저 회원가입을 수행합니다."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "회원가입 성공",
content = @Content(schema = @Schema(implementation = com.wayble.server.common.response.CommonResponse.class))),
@ApiResponse(responseCode = "400", description = "이미 존재하는 회원",
content = @Content(schema = @Schema(implementation = com.wayble.server.common.response.CommonResponse.class)))
})
public CommonResponse<String> signup(@RequestBody @Valid UserRegisterRequestDto req) {
userService.signup(req);
return CommonResponse.success("회원가입 성공");
}

// 예외 사용 참고용 컨트롤러(지우셔도 돼요)
@GetMapping("/ex")
public CommonResponse<String> exception() {
userService.makeException();
return CommonResponse.success("예외 발생!");
@PostMapping("/login")
@Operation(
summary = "유저 로그인",
description = "이메일+비밀번호 로그인 및 JWT 발급"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "로그인 성공",
content = @Content(schema = @Schema(implementation = com.wayble.server.common.response.CommonResponse.class))),
@ApiResponse(responseCode = "400", description = "아이디 혹은 비밀번호가 잘못됨",
content = @Content(schema = @Schema(implementation = com.wayble.server.common.response.CommonResponse.class)))
})
public CommonResponse<TokenResponseDto> login(@RequestBody @Valid UserLoginRequestDto req) {
TokenResponseDto tokenDto = authService.login(req);
return CommonResponse.success(tokenDto);
}

}
16 changes: 16 additions & 0 deletions src/main/java/com/wayble/server/user/dto/UserLoginRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.wayble.server.user.dto;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;

public record UserLoginRequestDto(
@NotBlank(message = "이름 또는 닉네임은 필수입니다")
String name,

@NotBlank(message = "이메일은 필수입니다")
@Email(message = "유효한 이메일 형식이 아닙니다")
String email,

@NotBlank(message = "비밀번호는 필수입니다")
String password
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,36 @@
import com.wayble.server.user.entity.Gender;
import com.wayble.server.user.entity.LoginType;
import com.wayble.server.user.entity.UserType;
import jakarta.validation.constraints.*;

import java.time.LocalDate;

public record UserRegisterRequestDto(
@NotBlank(message = "닉네임은 필수입니다")
@Size(max = 8, message = "닉네임은 8자 이하여야 합니다")
String nickname,

@NotBlank(message = "사용자명은 필수입니다")
String username,

@NotBlank(message = "이메일은 필수입니다")
@Email(message = "유효한 이메일 형식이 아닙니다")
String email,

@NotBlank(message = "비밀번호는 필수입니다")
@Size(min = 8, message = "비밀번호는 8자 이상이어야 합니다")
String password,

@NotNull(message = "생년월일은 필수입니다")
@Past(message = "생년월일은 과거 날짜여야 합니다")
LocalDate birthDate,

@NotNull(message = "성별은 필수입니다")
Gender gender,

@NotNull(message = "로그인 타입은 필수입니다")
LoginType loginType,

@NotNull(message = "사용자 타입은 필수입니다")
UserType userType
) {}
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.wayble.server.user.dto.token;

public record TokenResponseDto(String accessToken) {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보통 유저가 회원가입 할 때 accessToken과 refreshToken을 모두 발급하는 것으로 알고 있습니다!

refreshToken은 아예 관련 로직이 없고 accessToken만 존재하는데 이유가 궁금합니다!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refreshToken 저장 방법을 redis를 써서 저장해보고 싶었는데 해당 로직을 고민하고 있었습니다! 아직 토큰의 저장 방법 및 만료시 재발급, 갱신에 관한 흐름을 생각하고 있어서 우선 로그인,회원가입 로직을 구현하고 나서 추가적으로 구현할 생각이였습니다.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 저도 refreshToken 저장을 Redis에 저장하는게 제일 좋은 방법으로 알고 있습니다!

다만 저희가 프리티어인데 Elastic Search까지 써야 해서 redis 쓰면 터질 확률이 높아보여요 흑흑 (저도 그래서 추천 기능에 Redis 쓰고 싶은데 못 쓰고 있어요 ㅠㅠ)

rdb로도 repository 파서 refreshToken을 저장하긴 해서 그렇게 짜야할 수도 있어요 ㅠㅠ

22 changes: 22 additions & 0 deletions src/main/java/com/wayble/server/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,26 @@ public class User extends BaseEntity {

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserPlace> userPlaces = new ArrayList<>();

public static User createUser(
String nickname,
String username,
String email,
String password,
LocalDate birthDate,
Gender gender,
LoginType loginType,
UserType userType
) {
return User.builder()
.nickname(nickname)
.username(username)
.email(email)
.password(password)
.birthDate(birthDate)
.gender(gender)
.loginType(loginType)
.userType(userType)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public enum UserErrorCase implements ErrorCase {
USER_NOT_FOUND(404, 1001, "사용자를 찾을 수 없습니다."),
WAYBLE_ZONE_NOT_FOUND(404, 1002, "해당 웨이블존을 찾을 수 없습니다."),
PLACE_ALREADY_SAVED(400, 1003, "이미 저장한 장소입니다."),
INVALID_USER_ID(400, 1004, "요청 경로의 유저 ID와 바디의 유저 ID가 일치하지 않습니다.");
INVALID_USER_ID(400, 1004, "요청 경로의 유저 ID와 바디의 유저 ID가 일치하지 않습니다."),
USER_ALREADY_EXISTS(400, 1005, "이미 존재하는 회원입니다."),
INVALID_CREDENTIALS(400, 1006, "아이디 혹은 비밀번호가 잘못되었습니다.");

private final Integer httpStatusCode;
private final Integer errorCode;
Expand Down
Loading
Loading