feat(user-service): logout 기능, cookie 기능 추가, redis 설정 추가
- logout 기능 추가 - cookie 기능 추가 - redis 설정 추가
This commit is contained in:
@@ -38,6 +38,7 @@ dependencies {
|
||||
compileOnly 'org.springframework.boot:spring-boot-starter-oauth2-client'
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-config'
|
||||
/*implementation 'org.springframework.kafka:spring-kafka'*/
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
|
||||
|
||||
// https://mvnrepository.com/artifact/com.github.gavlyukovskiy/p6spy-spring-boot-starter
|
||||
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0'
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.justpickup.userservice.domain.jwt.exception;
|
||||
import com.justpickup.userservice.global.exception.CustomException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
public class TokenRefreshException extends CustomException {
|
||||
public class AccessTokenNotValidException extends CustomException {
|
||||
|
||||
public TokenRefreshException(String message) {
|
||||
public AccessTokenNotValidException(String message) {
|
||||
super(HttpStatus.FORBIDDEN, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.justpickup.userservice.domain.jwt.exception;
|
||||
|
||||
import com.justpickup.userservice.global.dto.Result;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class RefreshTokenNotValidException extends RuntimeException {
|
||||
|
||||
private Result result;
|
||||
|
||||
public RefreshTokenNotValidException(String message) {
|
||||
this.result = Result.createErrorResult(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.justpickup.userservice.domain.jwt.redis;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.redis.core.RedisHash;
|
||||
|
||||
|
||||
@Getter
|
||||
@RedisHash("refresh_token")
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class RefreshToken {
|
||||
|
||||
@Id
|
||||
private String userId;
|
||||
private String refreshTokenId;
|
||||
|
||||
public static RefreshToken of(String userId, String refreshTokenId) {
|
||||
RefreshToken refreshToken = new RefreshToken();
|
||||
refreshToken.userId = userId;
|
||||
refreshToken.refreshTokenId = refreshTokenId;
|
||||
return refreshToken;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.justpickup.userservice.domain.jwt.repository;
|
||||
|
||||
import com.justpickup.userservice.domain.jwt.redis.RefreshToken;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface RefreshTokenRedisRepository extends CrudRepository<RefreshToken, String> {
|
||||
}
|
||||
@@ -5,4 +5,5 @@ import com.justpickup.userservice.domain.user.dto.JwtTokenDto;
|
||||
public interface RefreshTokenService {
|
||||
void updateRefreshToken(Long id, String refreshToken);
|
||||
JwtTokenDto refreshJwtToken(String accessToken, String refreshToken);
|
||||
void logoutToken(String accessToken);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package com.justpickup.userservice.domain.jwt.service;
|
||||
|
||||
import com.justpickup.userservice.domain.jwt.exception.TokenRefreshException;
|
||||
import com.justpickup.userservice.domain.jwt.exception.AccessTokenNotValidException;
|
||||
import com.justpickup.userservice.domain.jwt.exception.RefreshTokenNotValidException;
|
||||
import com.justpickup.userservice.domain.jwt.redis.RefreshToken;
|
||||
import com.justpickup.userservice.domain.jwt.repository.RefreshTokenRedisRepository;
|
||||
import com.justpickup.userservice.global.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.domain.user.dto.JwtTokenDto;
|
||||
import com.justpickup.userservice.domain.user.entity.User;
|
||||
import com.justpickup.userservice.domain.user.exception.NotExistUserException;
|
||||
import com.justpickup.userservice.domain.user.repository.UserRepository;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -21,16 +27,18 @@ import java.util.stream.Collectors;
|
||||
@Transactional(readOnly = true)
|
||||
@Slf4j
|
||||
public class RefreshTokenServiceImpl implements RefreshTokenService {
|
||||
private final UserRepository userRepository;
|
||||
private final UserDetailsService userDetailsService;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final UserRepository userRepository;
|
||||
private final RefreshTokenRedisRepository refreshTokenRedisRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateRefreshToken(Long id, String refreshToken) {
|
||||
public void updateRefreshToken(Long id, String uuid) {
|
||||
User user = userRepository.findById(id)
|
||||
.orElseThrow(() -> new NotExistUserException("사용자 고유번호 : " + id + "는 없는 사용자입니다."));
|
||||
|
||||
user.changeRefreshToken(refreshToken);
|
||||
refreshTokenRedisRepository.save(RefreshToken.of(user.getId().toString(), uuid));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -38,36 +46,51 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
|
||||
public JwtTokenDto refreshJwtToken(String accessToken, String refreshToken) {
|
||||
String userId = jwtTokenProvider.getUserId(accessToken);
|
||||
|
||||
User user = userRepository.findById(Long.valueOf(userId))
|
||||
.orElseThrow(() -> new NotExistUserException("사용자 고유번호 : " + userId + "는 없는 사용자입니다."));
|
||||
RefreshToken findRefreshToken = refreshTokenRedisRepository.findById(userId)
|
||||
.orElseThrow(()
|
||||
-> new RefreshTokenNotValidException("사용자 고유번호 : " + userId + "는 등록된 리프레쉬 토큰이 없습니다.")
|
||||
);
|
||||
|
||||
// refresh token 검증
|
||||
if (!jwtTokenProvider.validateJwtToken(refreshToken)) {
|
||||
// 익셉션 발생 - 로그 아웃 후 로그인 페이지로 이동 처리
|
||||
user.deleteRefreshToken();
|
||||
throw new TokenRefreshException("Not validate jwt token = " + refreshToken);
|
||||
String findRefreshTokenId = findRefreshToken.getRefreshTokenId();
|
||||
if (!jwtTokenProvider.validateJwtToken(refreshToken) ||
|
||||
!jwtTokenProvider.equalRefreshTokenId(findRefreshTokenId, refreshToken)) {
|
||||
|
||||
refreshTokenRedisRepository.delete(findRefreshToken);
|
||||
throw new RefreshTokenNotValidException("Not validate jwt token = " + refreshToken);
|
||||
}
|
||||
|
||||
String userRefreshTokenId = user.getRefreshTokenId();
|
||||
if (!jwtTokenProvider.equalRefreshTokenId(userRefreshTokenId, refreshToken)) {
|
||||
// 익셉션 발생 - 로그인 아웃 후 로그인 페이지로 이동 처리
|
||||
user.deleteRefreshToken();
|
||||
throw new TokenRefreshException("Not equal jwt token! user = " + userRefreshTokenId +
|
||||
", refreshToken = " + refreshToken);
|
||||
}
|
||||
User findUser = userRepository.findById(Long.valueOf(userId))
|
||||
.orElseThrow(() -> new NotExistUserException("유저 고유 번호 : " + userId + "는 없는 유저입니다."));
|
||||
|
||||
Authentication authentication = jwtTokenProvider.getAuthentication(user.getEmail());
|
||||
// access token 생성
|
||||
Authentication authentication = getAuthentication(findUser.getEmail());
|
||||
List<String> roles = authentication.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||
|
||||
String newAccessToken = jwtTokenProvider.createJwtAccessToken(userId, "/refreshToken", roles);
|
||||
String newRefreshToken = jwtTokenProvider.createJwtRefreshToken();
|
||||
|
||||
user.changeRefreshToken(newRefreshToken);
|
||||
|
||||
return JwtTokenDto.builder()
|
||||
.accessToken(newAccessToken)
|
||||
.refreshToken(newRefreshToken)
|
||||
.refreshToken(refreshToken)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logoutToken(String accessToken) {
|
||||
if (!jwtTokenProvider.validateJwtToken(accessToken)) {
|
||||
// 예외 발생
|
||||
throw new AccessTokenNotValidException("access token is not valid");
|
||||
}
|
||||
|
||||
RefreshToken refreshToken = refreshTokenRedisRepository.findById(jwtTokenProvider.getUserId(accessToken))
|
||||
.orElseThrow(() -> new RefreshTokenNotValidException("refresh Token is not exist"));
|
||||
|
||||
refreshTokenRedisRepository.delete(refreshToken);
|
||||
}
|
||||
|
||||
public Authentication getAuthentication(String email) {
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,29 @@ package com.justpickup.userservice.domain.jwt.web;
|
||||
import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl;
|
||||
import com.justpickup.userservice.domain.user.dto.JwtTokenDto;
|
||||
import com.justpickup.userservice.global.dto.Result;
|
||||
import com.justpickup.userservice.global.utils.CookieProvider;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AuthController {
|
||||
|
||||
private final RefreshTokenServiceImpl refreshTokenServiceImpl;
|
||||
private final CookieProvider cookieProvider;
|
||||
|
||||
@GetMapping("/refreshToken")
|
||||
public ResponseEntity<Result> refreshToken(@RequestHeader("X-AUTH-TOKEN") String accessToken,
|
||||
@@ -27,7 +33,11 @@ public class AuthController {
|
||||
|
||||
JwtTokenDto jwtTokenDto = refreshTokenServiceImpl.refreshJwtToken(accessToken, refreshToken);
|
||||
|
||||
return ResponseEntity.ok(Result.createSuccessResult(new RefreshTokenResponse(jwtTokenDto)));
|
||||
ResponseCookie responseCookie = cookieProvider.createRefreshTokenCookie(refreshToken);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.header(HttpHeaders.SET_COOKIE, responseCookie.toString())
|
||||
.body(Result.createSuccessResult(new RefreshTokenResponse(jwtTokenDto)));
|
||||
}
|
||||
|
||||
@Data
|
||||
@@ -35,19 +45,22 @@ public class AuthController {
|
||||
@AllArgsConstructor
|
||||
static class RefreshTokenResponse {
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
|
||||
public RefreshTokenResponse(JwtTokenDto jwtTokenDto) {
|
||||
this.accessToken = jwtTokenDto.getAccessToken();
|
||||
this.refreshToken = jwtTokenDto.getRefreshToken();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
public ResponseEntity<Result> logout(@RequestHeader("X-AUTH-TOKEN") String accessToken,
|
||||
@RequestHeader("REFRESH-TOKEN") String refreshToken) {
|
||||
log.info("########### logout!");
|
||||
// TODO: 2022/02/16 logout 구현 필요
|
||||
return ResponseEntity.ok(Result.createSuccessResult("success"));
|
||||
|
||||
refreshTokenServiceImpl.logoutToken(accessToken);
|
||||
|
||||
ResponseCookie refreshCookie = cookieProvider.removeRefreshTokenCookie();
|
||||
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.header(HttpHeaders.SET_COOKIE, refreshCookie.toString())
|
||||
.body(Result.createErrorResult(""));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.justpickup.userservice.domain.user.entity;
|
||||
|
||||
import com.justpickup.userservice.domain.user.dto.StoreOwnerDto;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -15,8 +14,8 @@ public class StoreOwner extends User {
|
||||
private String businessNumber;
|
||||
|
||||
public StoreOwner(String email, String password, String name, String phoneNumber,
|
||||
String businessNumber, String refreshTokenId) {
|
||||
super(email, password, name, phoneNumber, refreshTokenId);
|
||||
String businessNumber) {
|
||||
super(email, password, name, phoneNumber);
|
||||
this.businessNumber = businessNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import javax.persistence.*;
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@DiscriminatorColumn(name = "DTYPE")
|
||||
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class User extends BaseEntity {
|
||||
public abstract class User extends BaseEntity {
|
||||
|
||||
@Id @GeneratedValue
|
||||
@Column(name = "user_id")
|
||||
@@ -26,8 +26,6 @@ public class User extends BaseEntity {
|
||||
|
||||
private String phoneNumber;
|
||||
|
||||
private String refreshTokenId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Role role;
|
||||
|
||||
@@ -42,19 +40,11 @@ public class User extends BaseEntity {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public User(String email, String password, String name, String phoneNumber, String refreshTokenId) {
|
||||
public User(String email, String password, String name, String phoneNumber) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.name = name;
|
||||
this.phoneNumber = phoneNumber;
|
||||
this.refreshTokenId = refreshTokenId;
|
||||
}
|
||||
|
||||
public void changeRefreshToken(String refreshToken) {
|
||||
this.refreshTokenId = refreshToken;
|
||||
}
|
||||
|
||||
public void deleteRefreshToken() {
|
||||
this.refreshTokenId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.justpickup.userservice.global.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class RedisConfig {
|
||||
|
||||
private final RedisProperties redisProperties;
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<?, ?> redisTemplate() {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory());
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new StringRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
package com.justpickup.userservice.global.exception;
|
||||
|
||||
import com.justpickup.userservice.domain.jwt.exception.RefreshTokenNotValidException;
|
||||
import com.justpickup.userservice.global.dto.Result;
|
||||
import com.justpickup.userservice.global.utils.CookieProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
@@ -11,9 +16,12 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
private final CookieProvider cookieProvider;
|
||||
|
||||
@ExceptionHandler(CustomException.class)
|
||||
public ResponseEntity customExceptionHandler(CustomException ce) {
|
||||
HttpStatus status = ce.getStatus();
|
||||
@@ -23,6 +31,16 @@ public class GlobalExceptionHandler {
|
||||
.body(errorResult);
|
||||
}
|
||||
|
||||
@ExceptionHandler(RefreshTokenNotValidException.class)
|
||||
public ResponseEntity customJwtExceptionHandler(RefreshTokenNotValidException e) {
|
||||
// 쿠키 삭제
|
||||
ResponseCookie responseCookie = cookieProvider.removeRefreshTokenCookie();
|
||||
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
||||
.header(HttpHeaders.SET_COOKIE, responseCookie.toString())
|
||||
.body(e.getResult());
|
||||
}
|
||||
|
||||
@ExceptionHandler(BindException.class)
|
||||
public ResponseEntity bindExceptionHandler(BindException exception) {
|
||||
return getValidationErrorBody(exception);
|
||||
|
||||
@@ -2,10 +2,13 @@ package com.justpickup.userservice.global.security;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.global.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.global.dto.LoginRequest;
|
||||
import com.justpickup.userservice.global.dto.Result;
|
||||
import com.justpickup.userservice.global.utils.CookieProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -16,6 +19,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
@@ -32,6 +36,7 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final RefreshTokenServiceImpl refreshTokenServiceImpl;
|
||||
private final CookieProvider cookieProvider;
|
||||
|
||||
// login 리퀘스트 패스로 오는 요청을 판단
|
||||
@Override
|
||||
@@ -69,14 +74,20 @@ public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFil
|
||||
|
||||
refreshTokenServiceImpl.updateRefreshToken(Long.valueOf(userId), jwtTokenProvider.getRefreshTokenId(refreshToken));
|
||||
|
||||
Map<String, String> tokens = Map.of(
|
||||
"access_token", accessToken,
|
||||
"refresh_token", refreshToken
|
||||
);
|
||||
// 쿠키 설정
|
||||
ResponseCookie refreshTokenCookie = cookieProvider.createRefreshTokenCookie(refreshToken);
|
||||
|
||||
Cookie cookie = cookieProvider.of(refreshTokenCookie);
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
response.addCookie(cookie);
|
||||
|
||||
new ObjectMapper().writeValue(response.getOutputStream(), tokens);
|
||||
// body 설정
|
||||
Map<String, String> tokens = Map.of(
|
||||
"access_token", accessToken
|
||||
);
|
||||
|
||||
new ObjectMapper().writeValue(response.getOutputStream(), Result.createSuccessResult(tokens));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.justpickup.userservice.global.security;
|
||||
|
||||
import com.justpickup.userservice.domain.jwt.service.RefreshTokenServiceImpl;
|
||||
import com.justpickup.userservice.domain.jwt.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.global.utils.JwtTokenProvider;
|
||||
import com.justpickup.userservice.domain.user.service.UserService;
|
||||
import com.justpickup.userservice.global.utils.CookieProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@@ -23,6 +24,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
private final BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final RefreshTokenServiceImpl refreshTokenServiceImpl;
|
||||
private final CookieProvider cookieProvider;
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
@@ -34,7 +36,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
LoginAuthenticationFilter loginAuthenticationFilter =
|
||||
new LoginAuthenticationFilter(authenticationManagerBean(), jwtTokenProvider, refreshTokenServiceImpl);
|
||||
new LoginAuthenticationFilter(authenticationManagerBean(), jwtTokenProvider, refreshTokenServiceImpl, cookieProvider);
|
||||
loginAuthenticationFilter.setFilterProcessesUrl("/login");
|
||||
|
||||
http.csrf().disable();
|
||||
@@ -45,7 +47,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
http.logout()
|
||||
.logoutUrl("/logout")
|
||||
.deleteCookies("");
|
||||
.deleteCookies("refresh-token");
|
||||
|
||||
http.oauth2Login()
|
||||
.defaultSuccessUrl("http://just-pickup.com:8000/customer-frontend-service/")
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.justpickup.userservice.global.utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
@Component
|
||||
public class CookieProvider {
|
||||
|
||||
@Value("${token.refresh-expired-time}")
|
||||
private String refreshTokenExpiredTime;
|
||||
|
||||
public ResponseCookie createRefreshTokenCookie(String refreshToken) {
|
||||
return ResponseCookie.from("refresh-token", refreshToken)
|
||||
.httpOnly(true)
|
||||
.secure(true)
|
||||
.path("/")
|
||||
.maxAge(Long.parseLong(refreshTokenExpiredTime)).build();
|
||||
}
|
||||
|
||||
public ResponseCookie removeRefreshTokenCookie() {
|
||||
return ResponseCookie.from("refresh-token", null)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Cookie of(ResponseCookie responseCookie) {
|
||||
Cookie cookie = new Cookie(responseCookie.getName(), responseCookie.getValue());
|
||||
cookie.setPath(responseCookie.getPath());
|
||||
cookie.setSecure(responseCookie.isSecure());
|
||||
cookie.setHttpOnly(responseCookie.isHttpOnly());
|
||||
cookie.setMaxAge((int) responseCookie.getMaxAge().getSeconds());
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.justpickup.userservice.domain.jwt.utils;
|
||||
package com.justpickup.userservice.global.utils;
|
||||
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
@@ -16,12 +16,9 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class JwtTokenProvider {
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
@Value("${token.access-expired-time}")
|
||||
private long ACCESS_EXPIRED_TIME;
|
||||
|
||||
@@ -60,29 +57,24 @@ public class JwtTokenProvider {
|
||||
.compact();
|
||||
}
|
||||
|
||||
public Authentication getAuthentication(String email) {
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
|
||||
}
|
||||
|
||||
public String getUserId(String token) {
|
||||
try {
|
||||
return getClaimsFromJwtToken(token).getBody().getSubject();
|
||||
} catch (ExpiredJwtException expiredJwtException) {
|
||||
return expiredJwtException.getClaims().getSubject();
|
||||
}
|
||||
return getClaimsFromJwtToken(token).getSubject();
|
||||
}
|
||||
|
||||
private Jws<Claims> getClaimsFromJwtToken(String token) {
|
||||
return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
|
||||
private Claims getClaimsFromJwtToken(String token) {
|
||||
try {
|
||||
return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
|
||||
} catch (ExpiredJwtException e) {
|
||||
return e.getClaims();
|
||||
}
|
||||
}
|
||||
|
||||
public String getRefreshTokenId(String token) {
|
||||
try {
|
||||
return getClaimsFromJwtToken(token).getBody().get("value").toString();
|
||||
} catch (ExpiredJwtException expiredJwtException) {
|
||||
return expiredJwtException.getClaims().get("value").toString();
|
||||
}
|
||||
return getClaimsFromJwtToken(token).get("value").toString();
|
||||
}
|
||||
|
||||
public List<String> getRoles(String token) {
|
||||
return (List<String>) getClaimsFromJwtToken(token).get("roles");
|
||||
}
|
||||
|
||||
public boolean validateJwtToken(String token) {
|
||||
@@ -26,6 +26,10 @@ spring:
|
||||
hibernate:
|
||||
default_batch_fetch_size: 1000
|
||||
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
|
||||
eureka:
|
||||
client:
|
||||
service-url:
|
||||
@@ -39,8 +43,6 @@ logging:
|
||||
level:
|
||||
com.justpickup: DEBUG
|
||||
|
||||
|
||||
|
||||
# jpa query, parameter 로그 (p6spy)
|
||||
decorator.datasource.p6spy:
|
||||
enable-logging: true
|
||||
@@ -48,4 +50,6 @@ decorator.datasource.p6spy:
|
||||
token:
|
||||
access-expired-time: 3600000
|
||||
refresh-expired-time: 604800000
|
||||
secret: my-secret
|
||||
secret: my-secret
|
||||
refresh-token-name: refresh-token
|
||||
access-token-name: access-token
|
||||
Reference in New Issue
Block a user