로그인 로직 수정중.

cks
강석 최 2023-12-14 18:00:33 +09:00
parent 8acdf81a02
commit 7b85736e39
8 changed files with 68 additions and 31 deletions

View File

@ -45,6 +45,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-validation'
developmentOnly 'org.springframework.boot:spring-boot-devtools' developmentOnly 'org.springframework.boot:spring-boot-devtools'

View File

@ -3,19 +3,25 @@ package com.dbnt.kcscbackend.config.jwt;
import com.dbnt.kcscbackend.auth.entity.UserInfo; import com.dbnt.kcscbackend.auth.entity.UserInfo;
import com.dbnt.kcscbackend.config.egov.EgovProperties; import com.dbnt.kcscbackend.config.egov.EgovProperties;
import com.dbnt.kcscbackend.config.jwt.redis.RefreshToken;
import com.dbnt.kcscbackend.config.jwt.redis.RefreshTokenRepository;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable; import java.io.Serializable;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID;
/** /**
* *
@ -44,9 +50,11 @@ public class EgovJwtTokenUtil implements Serializable{
private static final long serialVersionUID = -5180902194184255251L; private static final long serialVersionUID = -5180902194184255251L;
//public static final long JWT_TOKEN_VALIDITY = 24 * 60 * 60; //하루 //public static final long JWT_TOKEN_VALIDITY = 24 * 60 * 60; //하루
public static final long JWT_TOKEN_VALIDITY = (long) ((1 * 60 * 60) / 60) * 60; //토큰의 유효시간 설정, 기본 60분 public static final long JWT_ACCESS_TOKEN_VALIDITY = (30); //토큰의 유효시간 설정, 기본 60분 60*60
public static final String SECRET_KEY = EgovProperties.getProperty("Globals.jwt.secret"); public static final String SECRET_KEY = EgovProperties.getProperty("Globals.jwt.secret");
@Autowired
private RefreshTokenRepository refreshTokenRepository;
//retrieve username from jwt token //retrieve username from jwt token
public String getUserIdFromToken(String token) { public String getUserIdFromToken(String token) {
@ -74,17 +82,12 @@ public class EgovJwtTokenUtil implements Serializable{
} }
//generate token for user //generate token for user
public String generateToken(UserInfo loginVO) {
return doGenerateToken(loginVO);
}
//while creating the token - //while creating the token -
//1. Define claims of the token, like Issuer, Expiration, Subject, and the ID //1. Define claims of the token, like Issuer, Expiration, Subject, and the ID
//2. Sign the JWT using the HS512 algorithm and secret key. //2. Sign the JWT using the HS512 algorithm and secret key.
//3. According to JWS Compact Serialization(https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-3.1) //3. According to JWS Compact Serialization(https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-3.1)
// compaction of the JWT to a URL-safe string // compaction of the JWT to a URL-safe string
private String doGenerateToken(UserInfo loginVO) { public String generateAccessToken(UserInfo loginVO) {
Map<String, Object> claims = new HashMap<>(); Map<String, Object> claims = new HashMap<>();
claims.put("id", loginVO.getUserId() ); claims.put("id", loginVO.getUserId() );
claims.put("userSe", loginVO.getUserSe() ); claims.put("userSe", loginVO.getUserSe() );
@ -97,10 +100,18 @@ public class EgovJwtTokenUtil implements Serializable{
.setClaims(claims) .setClaims(claims)
.setSubject("Authorization") .setSubject("Authorization")
.setIssuedAt(new Date(System.currentTimeMillis())) .setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)) .setExpiration(new Date(System.currentTimeMillis() + JWT_ACCESS_TOKEN_VALIDITY * 1000))
.signWith(Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8)), SignatureAlgorithm.HS512); .signWith(Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8)), SignatureAlgorithm.HS512);
return builder.compact(); return builder.compact();
} }
@Transactional
public String generateRefreshTokenToken(UserInfo loginVO){
RefreshToken refreshToken = new RefreshToken();
refreshToken.setRefreshToken(UUID.randomUUID().toString());
refreshToken.setUserSeq(loginVO.getUserSeq());
refreshTokenRepository.save(refreshToken);
return refreshToken.getRefreshToken();
}
} }

View File

@ -0,0 +1,20 @@
package com.dbnt.kcscbackend.config.jwt.redis;
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@RedisHash(value="refreshToken", timeToLive = 60) // *60*24*14
public class RefreshToken {
@Id
private String refreshToken;
private Integer userSeq;
}

View File

@ -0,0 +1,8 @@
package com.dbnt.kcscbackend.config.jwt.redis;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface RefreshTokenRepository extends CrudRepository<RefreshToken, String> {
}

View File

@ -2,6 +2,7 @@ package com.dbnt.kcscbackend.config.security;
import com.dbnt.kcscbackend.auth.entity.UserInfo; import com.dbnt.kcscbackend.auth.entity.UserInfo;
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil; import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@ -49,12 +50,14 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
MediaType jsonMimeType = MediaType.APPLICATION_JSON; MediaType jsonMimeType = MediaType.APPLICATION_JSON;
String jwtToken = jwtTokenUtil.generateToken(securityUser); String refreshToken = jwtTokenUtil.generateRefreshTokenToken(securityUser);
String jwtToken = jwtTokenUtil.generateAccessToken(securityUser);
securityUser.setPassword(null); securityUser.setPassword(null);
securityUser.setUserSeq(null); securityUser.setUserSeq(null);
HashMap<String, Object> resultMap = new HashMap<String, Object>(); HashMap<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("resultCode", "200"); resultMap.put("resultCode", "200");
resultMap.put("resultVO", (UserDetails)securityUser); resultMap.put("resultVO", (UserDetails)securityUser);
resultMap.put("refreshToken", refreshToken);
resultMap.put("jToken", jwtToken); resultMap.put("jToken", jwtToken);
// String userName = jwtTokenUtil.getUserSeFromToken(jwtToken); // String userName = jwtTokenUtil.getUserSeFromToken(jwtToken);
response.addHeader("Authorization", "BEARER "+jwtToken); response.addHeader("Authorization", "BEARER "+jwtToken);

View File

@ -20,7 +20,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@Slf4j @Slf4j
public class JsonUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public class JsonAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private static final String DEFAULT_LOGIN_REQUEST_URL = "/auth/login"; // /login/oauth2/ + ????? 로 오는 요청을 처리할 것이다 private static final String DEFAULT_LOGIN_REQUEST_URL = "/auth/login"; // /login/oauth2/ + ????? 로 오는 요청을 처리할 것이다
private static final String HTTP_METHOD = "POST"; //HTTP 메서드의 방식은 POST 이다. private static final String HTTP_METHOD = "POST"; //HTTP 메서드의 방식은 POST 이다.
@ -30,7 +30,7 @@ public class JsonUsernamePasswordAuthenticationFilter extends AbstractAuthentica
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
public JsonUsernamePasswordAuthenticationFilter(ObjectMapper objectMapper, public JsonAuthenticationFilter(ObjectMapper objectMapper,
AuthenticationSuccessHandler authenticationSuccessHandler, // 로그인 성공 시 처리할 핸들러 AuthenticationSuccessHandler authenticationSuccessHandler, // 로그인 성공 시 처리할 핸들러
AuthenticationFailureHandler authenticationFailureHandler // 로그인 실패 시 처리할 핸들러 AuthenticationFailureHandler authenticationFailureHandler // 로그인 실패 시 처리할 핸들러
) { ) {

View File

@ -1,7 +1,5 @@
package com.dbnt.kcscbackend.config.security; package com.dbnt.kcscbackend.config.security;
import com.dbnt.kcscbackend.auth.entity.UserInfo;
import com.dbnt.kcscbackend.auth.service.EgovLoginService;
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil; import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationEntryPoint; import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationEntryPoint;
import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationFilter; import com.dbnt.kcscbackend.config.jwt.JwtAuthenticationFilter;
@ -16,28 +14,20 @@ import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Arrays; import java.util.Arrays;
/** /**
@ -55,8 +45,6 @@ import java.util.Arrays;
@RequiredArgsConstructor @RequiredArgsConstructor
public class SecurityConfig { public class SecurityConfig {
@Autowired
private EgovJwtTokenUtil jwtTokenUtil;
@Resource(name = "loginService") @Resource(name = "loginService")
private UserDetailsService loginService; private UserDetailsService loginService;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
@ -150,10 +138,10 @@ public class SecurityConfig {
} }
@Bean @Bean
public JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() { public JsonAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() {
JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(), loginFailureHandler()); JsonAuthenticationFilter jsonAuthenticationFilter = new JsonAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(), loginFailureHandler());
jsonUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager()); jsonAuthenticationFilter.setAuthenticationManager(authenticationManager());
return jsonUsernamePasswordAuthenticationFilter; return jsonAuthenticationFilter;
} }
@Bean @Bean

View File

@ -1,8 +1,14 @@
spring.mvc.pathmatch.matching-strategy=ant_path_matcher spring.mvc.pathmatch.matching-strategy=ant_path_matcher
# Page Config # Page Config
Globals.pageUnit=10 Globals.pageUnit=10
Globals.pageSize=10 Globals.pageSize=10
#JWT secret key #JWT
# redisConfig
spring.redis.host=localhost
spring.redis.port=6379
# secret key
Globals.jwt.secret = qWwMroux3QtiIJcPSIZARNTZEBBnWVH0jZ2Lx7tfFChCYi0ViZllo1bekZdiU0B3FRjJI7g90n0ha120dwlz8JZU8rOkmNCe9Uq0 Globals.jwt.secret = qWwMroux3QtiIJcPSIZARNTZEBBnWVH0jZ2Lx7tfFChCYi0ViZllo1bekZdiU0B3FRjJI7g90n0ha120dwlz8JZU8rOkmNCe9Uq0