Skip to content

Commit

Permalink
Merge branch 'develop' into test
Browse files Browse the repository at this point in the history
  • Loading branch information
gerry-mandering committed Apr 17, 2024
2 parents cbeb85f + 1bb21ce commit e106bca
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ jobs:
wait-for-service-stability: false
codedeploy-appspec: appspec.yml
codedeploy-application: ${{ env.CODEDEPLOY_APPLICATION }}
codedeploy-deployment-group: ${{ env.CODEDEPLOY_DEPLOYMENT_GROUP }}
codedeploy-deployment-group: ${{ env.CODEDEPLOY_DEPLOYMENT_GROUP }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,6 @@ application-*.yml
## Database Initialization ##
init.sql
init_test.sql


redis/data/
4 changes: 1 addition & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ dependencies {

implementation 'com.google.code.gson:gson:2.10.1'

// Redis
// TODO: 임시로 주석처리
// implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.2.2'

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
}
Expand Down
18 changes: 17 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,32 @@ services:
DB_SCHEMA: ${DB_SCHEMA}
DB_USER_PASSWORD: ${DB_USER_PASSWORD}
SPRING_PROFILES_ACTIVE: dev
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT}
REDIS_PASSWORD: ${REDIS_PASSWORD}
depends_on:
- mysql
- redis
networks:
- app-tier
restart: on-failure
tty: true

redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./redis.conf:/usr/local/etc/redis/redis.conf
command: redis-server /usr/local/etc/redis/redis.conf
networks:
- app-tier
restart: always

networks:
app-tier:
driver: bridge

volumes:
mysql-data: null
mysql-data:
redis-data:
4 changes: 4 additions & 0 deletions redis.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bind 0.0.0.0
port 6379
save 900 1
requirepass 1234
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.example.dreamvalutbackend.config.handler.CommonLoginSuccessHandler;
import com.example.dreamvalutbackend.config.jwt.filter.JwtVerifyFilter;
import com.example.dreamvalutbackend.config.oauth2.service.OAuth2UserService;
import com.example.dreamvalutbackend.redis.repository.TokenRepository;

import lombok.RequiredArgsConstructor;

Expand All @@ -32,6 +33,7 @@
public class SecurityConfig {

private final OAuth2UserService oAuth2UserService;
private final TokenRepository tokenRepository;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
Expand Down Expand Up @@ -70,7 +72,7 @@ public JwtVerifyFilter jwtVerifyFilter() {
}
@Bean
public CommonLoginSuccessHandler commonLoginSuccessHandler() {
return new CommonLoginSuccessHandler();
return new CommonLoginSuccessHandler(tokenRepository);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,46 @@
import com.example.dreamvalutbackend.config.jwt.utils.JwtConstants;
import com.example.dreamvalutbackend.config.jwt.utils.JwtUtils;
import com.example.dreamvalutbackend.domain.user.domain.UserDetailPrincipal;
import com.example.dreamvalutbackend.redis.domain.Token;
import com.example.dreamvalutbackend.redis.repository.TokenRepository;
import com.google.gson.Gson;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

@Slf4j
@Component
@RequiredArgsConstructor
public class CommonLoginSuccessHandler implements AuthenticationSuccessHandler {

private final TokenRepository tokenRepository;

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

UserDetailPrincipal principal = (UserDetailPrincipal) authentication.getPrincipal();


Map<String, Object> responseMap = principal.getUserInfo();

String refreshToken = JwtUtils.generateToken(responseMap, JwtConstants.REFRESH_EXP_TIME);

responseMap.put("accessToken", JwtUtils.generateToken(responseMap, JwtConstants.ACCESS_EXP_TIME));
responseMap.put("refreshToken", JwtUtils.generateToken(responseMap, JwtConstants.REFRESH_EXP_TIME));
responseMap.put("refreshToken", refreshToken);

Long userId = principal.getUserId();
Token token = new Token(refreshToken, userId);
tokenRepository.save(token);


Gson gson = new Gson();
String json = gson.toJson(responseMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.Map;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -11,35 +14,44 @@
import com.example.dreamvalutbackend.config.exception.CustomJwtException;
import com.example.dreamvalutbackend.config.jwt.utils.JwtConstants;
import com.example.dreamvalutbackend.config.jwt.utils.JwtUtils;
import com.example.dreamvalutbackend.redis.config.RedisConfiguration;
import com.example.dreamvalutbackend.redis.repository.TokenRepository;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class JwtController {

private final StringRedisTemplate stringRedisTemplate;

@PostMapping("/refresh")
public Map<String, Object> refresh(@RequestHeader("Authorization") String authHeader,@RequestParam String refreshToken) {
if (authHeader == null) {
throw new CustomJwtException("Access Token 이 존재하지 않습니다");
} else if (!authHeader.startsWith(JwtConstants.JWT_TYPE)) {
throw new CustomJwtException("BEARER 로 시작하지 않는 올바르지 않은 토큰 형식입니다");
public ResponseEntity<Map<String, Object>> refresh(@RequestHeader("Authorization") String authHeader, @RequestHeader("X-Refresh-Token") String refreshToken) {
if (authHeader == null || !authHeader.startsWith(JwtConstants.JWT_TYPE)) {
throw new CustomJwtException("Access Token 형식이 올바르지 않습니다.");
}

String accessToken = JwtUtils.getTokenFromHeader(authHeader);

if (!JwtUtils.isExpired(accessToken)) {
return Map.of("Access Token", accessToken, "Refresh Token", refreshToken);
return ResponseEntity.ok(Map.of("Access Token", accessToken, "Refresh Token", refreshToken));
}

Map<String, Object> claims = JwtUtils.validateToken(refreshToken);
String newAccessToken = JwtUtils.generateToken(claims, JwtConstants.ACCESS_EXP_TIME);
String userId = (String) claims.get("userId");
String storedToken = stringRedisTemplate.opsForValue().get("refreshToken:" + userId);
if (!refreshToken.equals(storedToken)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error", "Invalid refresh token"));
}


String newAccessToken = JwtUtils.generateToken(claims, JwtConstants.ACCESS_EXP_TIME);
String newRefreshToken = refreshToken;
long expTime = JwtUtils.tokenRemainTime((Integer) claims.get("exp"));
if (expTime <= 60) {
newRefreshToken = JwtUtils.generateToken(claims, JwtConstants.REFRESH_EXP_TIME);
}

return Map.of("accessToken", newAccessToken, "refreshToken", newRefreshToken);
return ResponseEntity.ok(Map.of("accessToken", newAccessToken, "refreshToken", newRefreshToken));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public static Authentication getAuthentication(String token) {

String email = (String) claims.get("email");
String name = (String) claims.get("name");
String role = (String) claims.get("role");
String role = (String) claims.get("role");
String userId = (String) claims.get("userId");
UserRole userRole = UserRole.valueOf(role);

User user = User.builder().userEmail(email).userName(name).role(userRole).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public Map<String, Object> getUserInfo() {
info.put("name", user.getUserName());
info.put("email", user.getUserEmail());
info.put("role", user.getRole().toString());
info.put("userId", user.getUserId().toString());
return info;
}

public Long getUserId() {
return user.getUserId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.example.dreamvalutbackend.redis.config;

import org.springframework.beans.factory.annotation.Value;
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.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfiguration {
@Value("${spring.data.redis.host}")
private String host;

@Value("${spring.data.redis.port}")
private int port;

@Value("${spring.data.redis.password}")
private String password;

@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);
config.setPassword(password);
return new LettuceConnectionFactory(config);
}

@Bean
public RedisTemplate<String, String> redisTemplate() {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
//StringRedisTemplate redisTemplate = new StringRedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.dreamvalutbackend.redis.controller;

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

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class RedisController {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.dreamvalutbackend.redis.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

import lombok.Getter;

@Getter
@RedisHash(value = "refreshToken", timeToLive = 86400)
public class Token {
@Id
private Long userId;

private String refreshToken;

public Token(String refreshToken, Long userId) {
this.refreshToken = refreshToken;
this.userId = userId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.dreamvalutbackend.redis.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.example.dreamvalutbackend.redis.domain.Token;

@Repository
public interface TokenRepository extends CrudRepository<Token, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.dreamvalutbackend.redis.service;

import org.springframework.stereotype.Service;

@Service
public class RedisService {

}

0 comments on commit e106bca

Please sign in to comment.