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
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ dependencies {

// Apache Commons Codec
implementation"commons-codec:commons-codec:1.19.0"

// Redis (Spring starter)
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}

dependencyManagement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ public ResponseEntity<RsData<Void>> logout(
* @param sessionId 쿠키에 포함된 현재 로그인한 사용자의 sessionId.
* @param response Servlet 기반 웹에서 server -> client로 http 응답을 보내기 위한 객체, 자동 주입.
*/

@PostMapping("/refresh")
@Operation(summary = "사용자 액세스 토큰 재발급 (서버 저장 RefreshToken 사용)")
public ResponseEntity<RsData<Void>> refreshToken(
@CookieValue(name = "sessionId")
String sessionId,
HttpServletResponse response
) {

if (sessionId == null) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
Expand All @@ -91,7 +89,11 @@ public ResponseEntity<RsData<Void>> refreshToken(
} catch (AuthenticationException e) {
return ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.body(new RsData<>("401", e.getMessage(), null));
.body(new RsData<>(
"401",
e.getMessage(),
null
));
}

String refreshToken = refreshTokenEntity.getRefreshToken();
Expand Down Expand Up @@ -126,7 +128,6 @@ public ResponseEntity<RsData<Void>> refreshToken(
* 확장프로그램의 액세스 토큰 발급을 위한 백그라운드 풀링에 대응하는 API
* @param state 확장프로그램 로그인 시 전달한 state 값.
*/

@GetMapping("/result")
@Operation(summary = "확장프로그램 백그라운드 풀링 대응 API")
public ResponseEntity<RsData<AuthResultData>> pullingResult(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package org.tuna.zoopzoop.backend.domain.auth.dto;

public class AuthResultData {
private final String accessToken;
private final String sessionId;

public AuthResultData(String accessToken, String sessionId) {
this.accessToken = accessToken;
this.sessionId = sessionId;
}

public String getAccessToken() {
return accessToken;
}

public String getSessionId() {
return sessionId;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AuthResultData implements Serializable {
private String accessToken;
private String sessionId;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
package org.tuna.zoopzoop.backend.domain.auth.entity;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.tuna.zoopzoop.backend.domain.auth.dto.AuthResultData;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import java.time.Duration;

@Component
@RequiredArgsConstructor
public class AuthResult {
private final Map<String, AuthResultData> results = new ConcurrentHashMap<>();
private final RedisTemplate<String, AuthResultData> redisTemplate;
private static final String PREFIX = "auth:result:";

public void put(String state, String accessToken, String sessionId) {
results.put(state, new AuthResultData(accessToken, sessionId));
AuthResultData data = new AuthResultData(accessToken, sessionId);
redisTemplate.opsForValue().set(PREFIX + state, data, Duration.ofMinutes(1)); // TTL 1분, 프론트단에선 백그라운드 풀링 형식으로 계속 작동할 것이므로.
}

public AuthResultData get(String state) {
return results.remove(state);
}

public void consume(String state) {
results.remove(state);
AuthResultData data = redisTemplate.opsForValue().get(PREFIX + state);
if (data != null) redisTemplate.delete("auth:" + state);
return data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.tuna.zoopzoop.backend.global.config.redis;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.tuna.zoopzoop.backend.domain.auth.dto.AuthResultData;

@Configuration
@EnableCaching
public class RedisConfig {

@Bean
public RedisTemplate<String, AuthResultData> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, AuthResultData> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);

// Key Serializer
template.setKeySerializer(new StringRedisSerializer());
// Value Serializer (JSON 직렬화)
template.setValueSerializer(new Jackson2JsonRedisSerializer<>(AuthResultData.class));

return template;
}
}
12 changes: 11 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ spring:
options:
model: meta-llama/llama-4-scout-17b-16e-instruct
temperature: 0
data: #RedisTemplate 등을 사용하기 위한 직접 연결용
redis:
host: localhost
port: 6379
timeout: 6000
cache: #Spring Cache를 사용하기 위한 Redis
type: redis
redis:
time-to-live: 300000
cache-null-values: false
key-prefix:

springdoc:
default-produces-media-type: application/json;charset=UTF-8
Expand All @@ -48,7 +59,6 @@ logging:
server:
port: 8080


app:
seed:
enabled: true