Skip to content
Open
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
7 changes: 6 additions & 1 deletion Backend/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ services:
- ./db:/var/lib/mysql
container_name: chat-db
ports:
- "3306:3306"
- "3306:3306"
memcached:
container_name: solsol-memcached
image: memcached:alpine
ports:
- 11211:11211
17 changes: 17 additions & 0 deletions Backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spring-cache</artifactId>
<version>4.1.3</version>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>simple-spring-memcached</artifactId>
<version>4.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.simple-spring-memcached/xmemcached-provider -->
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>xmemcached-provider</artifactId>
<version>4.1.3</version>
</dependency>


</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@EnableCaching
@SpringBootApplication
public class SolsolApplication {
public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

import kimjang.toolkit.solsol.config.filter.*;
import kimjang.toolkit.solsol.config.provider.JwtAuthenticationProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
Expand Down Expand Up @@ -152,8 +149,4 @@ public PasswordEncoder passwordEncoder(){
// BCrypt 알고리즘을 이용해서 비밀번호를 해싱하자
return new BCryptPasswordEncoder();
}




}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package kimjang.toolkit.solsol.config.cache;

import com.google.code.ssm.Cache;
import com.google.code.ssm.CacheFactory;
import com.google.code.ssm.config.AddressProvider;
import com.google.code.ssm.config.DefaultAddressProvider;
import com.google.code.ssm.providers.CacheConfiguration;
import com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl;
import com.google.code.ssm.spring.ExtendedSSMCacheManager;
import com.google.code.ssm.spring.SSMCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;

@Slf4j
@Configuration
public class CacheConfig extends CachingConfigurerSupport {

@Value("${spring.cache.address}")
private String address;

@Value("${spring.cache.operationTimeout}")
private String operationTimeout;

@Value("${spring.cache.cacheName}")
private String cacheName;

@Value("${spring.cache.expiration}")
private String expiration;

@Bean
public CacheManager cacheManager() {

CacheFactory cacheFactory = getCacheFactory();

Cache object = null;

try {
object = cacheFactory.getObject();
} catch (Exception e) {
log.error(e.getMessage(), e);
}

SSMCache ssmCache = new SSMCache(object, Integer.parseInt(expiration), true);

ArrayList<SSMCache> ssmCaches = new ArrayList<>();
ssmCaches.add(0, ssmCache);

ExtendedSSMCacheManager ssmCacheManager = new ExtendedSSMCacheManager();
ssmCacheManager.setCaches(ssmCaches);

return ssmCacheManager;
}

private CacheFactory getCacheFactory() {
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setConsistentHashing(true);
cacheConfiguration.setUseBinaryProtocol(true);
cacheConfiguration.setOperationTimeout(Integer.getInteger(operationTimeout));
cacheConfiguration.setUseNameAsKeyPrefix(true);
cacheConfiguration.setKeyPrefixSeparator(":");

MemcacheClientFactoryImpl cacheClientFactory = new MemcacheClientFactoryImpl();

AddressProvider addressProvider = new DefaultAddressProvider(address);

CacheFactory cacheFactory = new CacheFactory();
cacheFactory.setCacheName(cacheName);
cacheFactory.setCacheClientFactory(cacheClientFactory);
cacheFactory.setAddressProvider(addressProvider);
cacheFactory.setConfiguration(cacheConfiguration);
return cacheFactory;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package kimjang.toolkit.solsol.config.cache;

import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

@Component
public class TokenHasher{
public String encode(String token){
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] encodedhash = digest.digest(token.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encodedhash);
}

public boolean matches(String rawToken, String hashedToken) {
String hashedRawToken = encode(rawToken);
return hashedRawToken.equals(hashedToken);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package kimjang.toolkit.solsol.config.handler;


import kimjang.toolkit.solsol.room.service.ChatRoomSubscribeService;
import kimjang.toolkit.solsol.domain.room.service.ChatRoomSubscribeService;
import kimjang.toolkit.solsol.config.container.SocketSessionContainer;
import kimjang.toolkit.solsol.config.jwt.SecurityConstants;
import kimjang.toolkit.solsol.config.provider.JwtAuthenticationProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.security.authentication.BadCredentialsException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package kimjang.toolkit.solsol.config.provider;

import kimjang.toolkit.solsol.user.entities.Authority;
import kimjang.toolkit.solsol.user.entities.User;
import kimjang.toolkit.solsol.user.reposiotry.UserRepository;
import kimjang.toolkit.solsol.domain.user.entities.Authority;
import kimjang.toolkit.solsol.domain.user.entities.User;
import kimjang.toolkit.solsol.domain.user.reposiotry.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package kimjang.toolkit.solsol.domain.cache;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RefreshToken {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@Column(name = "token_id") // 컬럼의 이름을 바꿀 수 있다.
private Long id;

private String email;

@Column(name = "refresh_token")
private String refreshToken;

public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package kimjang.toolkit.solsol.domain.cache;

import kimjang.toolkit.solsol.exception.UnauthorizedException;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class RefreshTokenCacheService {

private final RefreshTokenRepository refreshTokenRepository;

/**
* CachePut은 캐시가 있더라도 메서드를 실행한 결과를 Cache에 저장
* 따라서 무조건 새로운 token을 저장하고 싶은 경우 적절
* 한 메일에 한 refresh token만 가능!
*
* @param email
* @param hashedRefreshToken : hashing된 refresh token
* @return
*/
@CachePut(value= "refresh", key="#email")
public String saveToken(String email, String hashedRefreshToken){
Optional<RefreshToken> token = refreshTokenRepository.findByEmail(email);
if(token.isPresent()){ // 예전에 로그인해서 refresh token이 남아 있는 경우 업데이트
token.get().setRefreshToken(hashedRefreshToken);
return refreshTokenRepository.save(token.get()).getRefreshToken();
} else{ // 처음 refresh token 만들어서 저장하는 경우
RefreshToken newToken = RefreshToken.builder()
.email(email)
.refreshToken(hashedRefreshToken)
.build();
return refreshTokenRepository.save(newToken).getRefreshToken();
}
}

@CacheEvict(value = "refresh", key = "#email")
public void deleteCache(String email){}

/**
* 재발급 용도로 저장된 token 검색
* @param email
* @return
*/
@Cacheable(value= "refresh")
public String searchToken(String email){
return refreshTokenRepository.findByEmail(email)
.orElseThrow(()-> new UnauthorizedException("인증되지 않았습니다. 다시 시도해주세요.")).getRefreshToken();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package kimjang.toolkit.solsol.domain.cache;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
Optional<RefreshToken> findByEmail(String email);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package kimjang.toolkit.solsol.message;
package kimjang.toolkit.solsol.domain.message;

import jakarta.persistence.*;
import kimjang.toolkit.solsol.user.entities.User;
import kimjang.toolkit.solsol.message.dto.SendChatMessageDto;
import kimjang.toolkit.solsol.room.entity.ChatRoom;
import kimjang.toolkit.solsol.domain.message.dto.SendChatMessageDto;
import kimjang.toolkit.solsol.domain.room.entity.ChatRoom;
import kimjang.toolkit.solsol.domain.user.entities.User;
import lombok.*;

import java.time.LocalDateTime;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kimjang.toolkit.solsol.message;
package kimjang.toolkit.solsol.domain.message;

public class Greeting {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package kimjang.toolkit.solsol.message;
package kimjang.toolkit.solsol.domain.message;

import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.HtmlUtils;

@Controller
public class GreetingController {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kimjang.toolkit.solsol.message;
package kimjang.toolkit.solsol.domain.message;

public class HelloMessage {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package kimjang.toolkit.solsol.message.controllor;
package kimjang.toolkit.solsol.domain.message.controllor;

import kimjang.toolkit.solsol.message.dto.PastChatsDto;
import kimjang.toolkit.solsol.message.dto.ReqPastChatsDto;
import kimjang.toolkit.solsol.message.service.ChatService;
import kimjang.toolkit.solsol.domain.message.dto.ReqPastChatsDto;
import kimjang.toolkit.solsol.domain.message.service.ChatService;
import kimjang.toolkit.solsol.domain.message.dto.PastChatsDto;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.Date;

@RestController
@RequiredArgsConstructor
public class ChatController {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package kimjang.toolkit.solsol.message.dto;
package kimjang.toolkit.solsol.domain.message.dto;

import kimjang.toolkit.solsol.user.dto.UserDto;
import kimjang.toolkit.solsol.domain.user.dto.UserDto;

import java.time.LocalDateTime;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kimjang.toolkit.solsol.message.dto;
package kimjang.toolkit.solsol.domain.message.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kimjang.toolkit.solsol.message.dto;
package kimjang.toolkit.solsol.domain.message.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down
Loading