Skip to content

Commit

Permalink
Merge pull request #13 from nhnacademy-be5-T3Team/fix/redisDao
Browse files Browse the repository at this point in the history
Fix/redis dao
  • Loading branch information
joohyun1996 authored Apr 16, 2024
2 parents e6ea112 + ebba9ee commit 1e0876c
Show file tree
Hide file tree
Showing 24 changed files with 217 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
import java.util.ArrayList;
import java.util.Collection;

/**
* UserDetails 를 구현하는 CustomUserDetails Class
* JWT 토큰에 들어가는 UserId, UserRole, Password를 반환하게 설정함
* @author joohyun1996 (이주현)
*/
public class CustomUserDetails implements UserDetails {
private final UserEntity userEntity;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.t3t.authenticationapi.account.common;

import com.t3t.authenticationapi.account.exception.CookieNotExistException;
import com.t3t.authenticationapi.account.exception.TokenAlreadyExistsException;
import com.t3t.authenticationapi.account.exception.TokenHasExpiredException;
import com.t3t.authenticationapi.account.exception.TokenNotExistsException;
Expand All @@ -12,23 +11,31 @@

@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* access, refresh 토큰이 없을 경우에 대한 예외 처리 핸들러
* @return 403 Forbidden - 예외 메시지 반한
* @author joohyun1996 (이주현)
*/
@ExceptionHandler(TokenNotExistsException.class)
public ResponseEntity<BaseResponse<Void>> handleTokenNotExistsException(TokenNotExistsException tokenNotExistsException){
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new BaseResponse<Void>().message(tokenNotExistsException.getMessage()));
}

/**
* access 토큰이 만료된 경우에 대한 예외 처리 핸들러
* @return 403 Forbidden - 예외 메시지 반한
* @author joohyun1996 (이주현)
*/
@ExceptionHandler(TokenHasExpiredException.class)
public ResponseEntity<BaseResponse<Void>> handleTokenHasExpiredException(TokenHasExpiredException tokenHasExpiredException){
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new BaseResponse<Void>().message(tokenHasExpiredException.getMessage()));
}

/**
* refresh, blacklist 토큰이 이미 Redis에 저장되어 있을 경우에 대한 예외 처리 핸들러
* @return 400 Forbidden - 예외 메시지 반한
* @author joohyun1996 (이주현)
*/
@ExceptionHandler(TokenAlreadyExistsException.class)
public ResponseEntity<BaseResponse<Void>> handleTokenAlreadyExistsException(TokenAlreadyExistsException tokenAlreadyExistsException){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new BaseResponse<Void>().message(tokenAlreadyExistsException.getMessage()));
}

@ExceptionHandler(CookieNotExistException.class)
public ResponseEntity<BaseResponse<Void>> handleCookieNotExistsException(CookieNotExistException cookieNotExistException){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new BaseResponse<Void>().message(cookieNotExistException.getMessage()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
import java.time.ZoneId;
import java.util.Date;

/**
* JWT 토큰 발급 및 claim을 사용하는 Util 클래스
* @author joohyun1996 (이주현)
*/
@Component
public class JWTUtils {
private Key key;
Expand All @@ -33,11 +37,20 @@ public String getRole(String token){
public String getCategory(String token){
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().get("category", String.class);
}
/**
* access token과 refresh 토큰을 1대1로 맵핑해주는 임의의 UUID value
* @return String uuid
* @author joohyun1996 (이주현)
*/

public String getUUID(String token){
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().get("uuid", String.class);
}
// 만료되었으면 true, 아니면 false
/**
* 토큰이 만료되었는지 확인하는 메소드
* @return true if expired. else false
* @author joohyun1996 (이주현)
*/
public Boolean isExpired(String token){
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().getExpiration().before(new Date());
}
Expand All @@ -54,7 +67,11 @@ public String createJwt(String category, String id, String role, String uuid, Lo
.signWith(key, SignatureAlgorithm.HS256)
.compact();
}

/**
* access token 자동 재발급의 경우, 토큰의 잔여 시간이 5분 이하인지 check
* @return true / false
* @author joohyun1996 (이주현)
*/
public Boolean checkReIssue(String token){
Date expiration = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().getExpiration();
LocalDateTime localDateTime = LocalDateTime.ofInstant(expiration.toInstant(), ZoneId.systemDefault());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.StringRedisSerializer;


/**
* redis 연결을 위한 configuration 클래스
* @author joohyun1996 (이주현)
*/
@Configuration
@EnableRedisRepositories
public class RedisConfig {
Expand All @@ -31,8 +34,8 @@ public class RedisConfig {
* getConnection() 호출될 때 마다 새로운 LettuceConnection 생성
* Thread-safe 하다
* 동기, 비동기, 리액티브 api 모두 가능
*/

* @author joohyun1996 (이주현)
*/
@Bean
public RedisConnectionFactory redisConnectionFactory(){
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(host, port);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;

/**
* Spring Security 등록을 위한 configuration 클래스
* @author joohyun1996 (이주현)
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
Expand All @@ -35,7 +38,12 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration a
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}

/**
* Security Filter Chain 설정.
* Auth-Server에서는 인증만 담당하기 때문에 다른 URL에 대해서는 설정 X
* @param HttpSecurity
* @author joohyun1996 (이주현)
*/
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
Expand All @@ -44,6 +52,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.httpBasic().disable()
.authorizeRequests((auth) -> auth
.antMatchers("/login").permitAll()
.antMatchers("/logins").permitAll()
.antMatchers("/refresh").permitAll()
.antMatchers("/logout").authenticated()
.anyRequest().authenticated())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
package com.t3t.authenticationapi.account.controller;

import com.t3t.authenticationapi.account.service.DefaultUserDetailsService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

import java.util.Map;
/**
* Login 요청을 받는 RestController 클래스, 실제로는 UsernamePasswordAuthenticationFilter 때문에 동작하지 않는다.
* @author joohyun1996 (이주현)
*/
@RestController
public class LoginController {
private final DefaultUserDetailsService service;

public LoginController(DefaultUserDetailsService service) {
this.service = service;
}

/**
* LoginFilter 수행시 successfulAuthentication 메소드가 수행되고 해당 메소드에서 응답이 커밋됨
* @author joohyun1996(이주현)
*/
@PostMapping("/login")
public String doLogin(HttpServletRequest request){
// LoginFilter 수행시 successfulAuthentication 메소드가 수행되고 해당 메소드에서 응답이 커밋됨
return "login";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* Logout 요청을 받는 RestController 클래스, 실제로는 LogoutFilter 때문에 동작하지 않는다.
* @author joohyun1996 (이주현)
*/
@RestController
public class LogoutController {
@PostMapping("/logout")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* access token의 재발급을 담당하는 rest controller
* @author joohyun1996 (이주현)
*/
@RestController
@RequiredArgsConstructor
public class RefreshController {
private final DefaultRefreshService defaultRefreshService;

/**
* 토큰 재발급을 위한 api
* @param request,response
* @return 200 OK - access token 재발급
* 403 Forbidden - access & refresh 만료시
* @author joohyun1996 (이주현)
*/
@PostMapping("/refresh")
public ResponseEntity<?> refresh(HttpServletRequest request, HttpServletResponse response) {
return defaultRefreshService.refresh(request,response);
Expand Down
35 changes: 0 additions & 35 deletions src/main/java/com/t3t/authenticationapi/account/dao/RedisDao.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import lombok.experimental.SuperBuilder;

import javax.persistence.*;

/**
* 회원의 로그인 아이디를 담당하는 엔티티
* @author joohyun1996 (이주현)
*/
@Getter
@Entity@Table(name = "accounts")
@SuperBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

/**
* logout 된 access token을 redis에 저장하는 엔티티
* @author joohyun1996 (이주현)
*/
@Builder
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import lombok.experimental.SuperBuilder;

import javax.persistence.*;

/**
* 회원의 password를 저장하는 엔티티
* @author joohyun1996 (이주현)
*/
@Getter
@Entity@Table(name = "bookstore_accounts")
@SuperBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;


/**
* refresh 토큰을 redis에 저장하는 엔티티
* @author joohyun1996 (이주현)
*/
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.t3t.authenticationapi.account.exception;

import java.io.IOException;

/**
* 로그인시 회원의 id, pw에 해당하는 Json 객체가 올바르지 않은경우 발생하는 예외
* @author joohyun1996 (이주현)
*/
public class JsonFieldNotMatchException extends RuntimeException{
public JsonFieldNotMatchException(IOException e) {
super(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.t3t.authenticationapi.account.exception;

/**
* 새로운 토큰을 발급하는데, 이미 토큰이 존재하는 경우 발생하는 예외
* @author joohyun1996 (이주현)
*/
public class TokenAlreadyExistsException extends RuntimeException{
public TokenAlreadyExistsException(String e) {
super(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.t3t.authenticationapi.account.exception;

/**
* 만료된 토큰으로 접근시 발생하는 예외
* @author joohyun1996 (이주현)
*/
public class TokenHasExpiredException extends RuntimeException{
public TokenHasExpiredException(String s) {
super(s);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.t3t.authenticationapi.account.exception;

/**
* auth - server로 접근하는 토큰에 대한 refresh토큰이 없는경우 발생하는 예외
* @author joohyun1996 (이주현)
*/
public class TokenNotExistsException extends RuntimeException{
public TokenNotExistsException(String s) {
super(s);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* Login, Logout Filter에서 발생하는 예외를 공통처리하는 Filter
* @author joohyun1996 (이주현)
*/
public class CommonExceptionFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Expand Down
Loading

0 comments on commit 1e0876c

Please sign in to comment.