Skip to content

Commit

Permalink
Merge pull request #38 from peeerr/session
Browse files Browse the repository at this point in the history
Redis를 사용하여 분산 환경에서의 세션 불일치 문제 해결하기
  • Loading branch information
peeerr authored Apr 2, 2024
2 parents ab792cd + 7e5245a commit 31e157c
Show file tree
Hide file tree
Showing 78 changed files with 868 additions and 327 deletions.
10 changes: 0 additions & 10 deletions .ebextensions/00-makefile.config

This file was deleted.

17 changes: 5 additions & 12 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: climb
name: climbing
on:
push:
branches:
Expand All @@ -24,6 +24,7 @@ jobs:
with:
files: ./src/main/resources/application-ci.yml, ./src/main/resources/application-prod.yml
env:
spring.data.redis.host: ${{ secrets.REDIS_HOSTNAME }}
aws.s3.bucket: ${{ secrets.AWS_S3_BUCKET }}
aws.s3.accessKey: ${{ secrets.AWS_S3_ACCESS_KEY }}
aws.s3.secretKey: ${{ secrets.AWS_S3_SECRET_KEY }}
Expand All @@ -41,16 +42,8 @@ jobs:
format: YYYY-MM-DDTHH-mm-ss
utfOffset: "+09:00"

- name: Show Current Time
run: echo "${{steps.current-time.outputs.formattedTime}}"

- name: Create deployment zip file
run: |
mkdir -p deploy
cp build/libs/*.jar deploy/application.jar
cp Procfile deploy/Procfile
cp -r .ebextensions deploy/.ebextensions
cd deploy && zip -r deploy.zip .
- name: Generate deployment package
run: zip -r deploy.zip .

# EB에 배포
- name: Deploy to EB
Expand All @@ -62,4 +55,4 @@ jobs:
environment_name: Climbing-env
version_label: climbing-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: deploy/deploy.zip
deployment_package: deploy.zip
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM openjdk:17-alpine

WORKDIR /app

COPY . .

RUN sed -i 's/\r$//' gradlew

RUN chmod +x ./gradlew
RUN ./gradlew clean build

ENV JAR_PATH=/app/build/libs
RUN mv ${JAR_PATH}/*.jar /app/app.jar

ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"]
1 change: 0 additions & 1 deletion Procfile

This file was deleted.

4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ dependencies {
// Spring Rest Docs
asciidoctorExt "org.springframework.restdocs:spring-restdocs-asciidoctor:${asciidocVersion}"
testImplementation "org.springframework.restdocs:spring-restdocs-mockmvc:${asciidocVersion}"

// Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.session:spring-session-data-redis'
}

// test 할 때 snippetsDir 에 생성된 응답을 asciidoctor 로 변환하여 .adoc 파일 생성
Expand Down
25 changes: 24 additions & 1 deletion src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ include::{snippets}/post-remove/response-fields.adoc[]

== 회원 API

=== POST /api/members [회원가입]
=== POST /api/members/register [회원가입]

==== 요청

Expand All @@ -98,6 +98,29 @@ include::{snippets}/member-create/request-fields.adoc[]
include::{snippets}/member-create/http-response.adoc[]
include::{snippets}/member-create/response-fields.adoc[]

=== POST /api/members/login [로그인]

==== 요청

include::{snippets}/member-login/http-request.adoc[]
include::{snippets}/member-login/request-fields.adoc[]

==== 응답

include::{snippets}/member-login/http-response.adoc[]
include::{snippets}/member-login/response-fields.adoc[]

=== POST /api/members/logout [로그아웃]

==== 요청

include::{snippets}/member-logout/http-request.adoc[]

==== 응답

include::{snippets}/member-logout/http-response.adoc[]
include::{snippets}/member-logout/response-fields.adoc[]

=== PUT /api/members/{memberId} [회원정보 변경]

==== 요청
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.peeerr.climbing.dto.post.response;
package com.peeerr.climbing.dto.post;

import com.querydsl.core.types.dsl.*;

import com.querydsl.core.types.ConstructorExpression;
import javax.annotation.processing.Generated;

/**
* com.peeerr.climbing.dto.post.response.QPostResponse is a Querydsl Projection type for PostResponse
* com.peeerr.climbing.dto.post.QPostResponse is a Querydsl Projection type for PostResponse
*/
@Generated("com.querydsl.codegen.DefaultProjectionSerializer")
public class QPostResponse extends ConstructorExpression<PostResponse> {

private static final long serialVersionUID = -1231495484L;
private static final long serialVersionUID = -923548853L;

public QPostResponse(com.querydsl.core.types.Expression<Long> postId, com.querydsl.core.types.Expression<String> categoryName, com.querydsl.core.types.Expression<String> writer, com.querydsl.core.types.Expression<java.time.LocalDateTime> createDate, com.querydsl.core.types.Expression<java.time.LocalDateTime> modifyDate) {
super(PostResponse.class, new Class<?>[]{long.class, String.class, String.class, java.time.LocalDateTime.class, java.time.LocalDateTime.class}, postId, categoryName, writer, createDate, modifyDate);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.peeerr.climbing.exception;
package com.peeerr.climbing.advice;

import com.peeerr.climbing.dto.common.ApiResponse;
import com.peeerr.climbing.exception.constant.ErrorMessage;
import com.peeerr.climbing.exception.ex.*;
import com.peeerr.climbing.dto.ApiResponse;
import com.peeerr.climbing.constant.ErrorMessage;
import com.peeerr.climbing.exception.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.peeerr.climbing.aop;

import com.peeerr.climbing.exception.constant.ErrorMessage;
import com.peeerr.climbing.exception.ex.ValidationException;
import com.peeerr.climbing.constant.ErrorMessage;
import com.peeerr.climbing.exception.ValidationException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/com/peeerr/climbing/config/RedisConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.peeerr.climbing.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.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

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

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

@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setDefaultSerializer(new StringRedisSerializer());

return redisTemplate;
}

}
39 changes: 16 additions & 23 deletions src/main/java/com/peeerr/climbing/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,51 +1,44 @@
package com.peeerr.climbing.config;

import com.peeerr.climbing.config.auth.CustomAuthFailureHandler;
import com.peeerr.climbing.config.auth.CustomUserDetailsService;
import com.peeerr.climbing.security.CustomAuthenticationEntryPoint;
import com.peeerr.climbing.security.MemberAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@RequiredArgsConstructor
@Configuration
public class SecurityConfig {

private final CustomUserDetailsService customUserDetailsService;
private final CustomAuthFailureHandler failureHandler;
private final MemberAuthenticationFilter memberAuthenticationFilter;
private final CustomAuthenticationEntryPoint entryPoint;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(c -> c.disable())
.formLogin(form -> form
.usernameParameter("email")
.loginProcessingUrl("/api/members/login")
.failureHandler(failureHandler))
.addFilterBefore(memberAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/members/**").permitAll()
.requestMatchers(HttpMethod.POST, "/api/members/**").permitAll()
.requestMatchers(HttpMethod.GET,"/").permitAll()
.requestMatchers(HttpMethod.GET, "/api/posts/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/categories/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/posts/{postId}/files/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/posts/{postId}/likes/**").permitAll()
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll());
.anyRequest().permitAll())
.exceptionHandling(ex -> ex
.authenticationEntryPoint(entryPoint));

return http.build();
}

@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();

provider.setUserDetailsService(customUserDetailsService);
provider.setPasswordEncoder(passwordEncoder());
provider.setHideUserNotFoundExceptions(false);

return provider;
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.peeerr.climbing.exception.constant;
package com.peeerr.climbing.constant;

public class ErrorMessage {

Expand All @@ -14,13 +14,13 @@ public class ErrorMessage {

/* StorageManagement */
public static final String FILE_STORE_FAILED = "파일 저장에 실패했습니다.";
public static final String DIRECTORY_CREATE_FAILED = "파일을 저장할 디렉토리 생성에 실패했습니다.";

/* S3FileUploader */
public static final String INVALID_FILE_TYPE = "이미지 파일 형식만 첨부가 가능합니다. (JPEG, PNG, GIF)";

/* UserService */
/* MemberService */
public static final String PASSWORD_CONFIRMATION_FAILED = "비밀번호 확인에 실패했습니다. 동일한 비밀번호를 입력해 주세요.";
public static final String INVALID_PASSWORD = "비밀번호가 일치하지 않습니다.";
public static final String USERNAME_DUPLICATED = "이미 존재하는 닉네임입니다.";
public static final String EMAIL_DUPLICATED = "이미 존재하는 이메일입니다.";

Expand All @@ -37,6 +37,7 @@ public class ErrorMessage {
/* Member */
public static final String MEMBER_NOT_FOUND = "존재하지 않는 아이디입니다.";
public static final String NO_ACCESS_PERMISSION = "접근 권한이 없습니다.";
public static final String LOGIN_REQUIRED = "로그인 후 이용해 주세요.";

/* File */
public static final String FILE_NOT_FOUND = "존재하지 않는 파일입니다.";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.peeerr.climbing.controller;

import com.peeerr.climbing.dto.category.request.CategoryCreateRequest;
import com.peeerr.climbing.dto.category.request.CategoryEditRequest;
import com.peeerr.climbing.dto.category.response.CategoryResponse;
import com.peeerr.climbing.dto.common.ApiResponse;
import com.peeerr.climbing.dto.category.CategoryCreateRequest;
import com.peeerr.climbing.dto.category.CategoryEditRequest;
import com.peeerr.climbing.dto.category.CategoryResponse;
import com.peeerr.climbing.dto.ApiResponse;
import com.peeerr.climbing.service.CategoryService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.peeerr.climbing.controller;

import com.peeerr.climbing.config.auth.CustomUserDetails;
import com.peeerr.climbing.dto.comment.request.CommentCreateRequest;
import com.peeerr.climbing.dto.comment.request.CommentEditRequest;
import com.peeerr.climbing.dto.common.ApiResponse;
import com.peeerr.climbing.security.CustomUserDetails;
import com.peeerr.climbing.dto.comment.CommentCreateRequest;
import com.peeerr.climbing.dto.comment.CommentEditRequest;
import com.peeerr.climbing.dto.ApiResponse;
import com.peeerr.climbing.service.CommentService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.peeerr.climbing.controller;

import com.peeerr.climbing.config.auth.CustomUserDetails;
import com.peeerr.climbing.dto.common.ApiResponse;
import com.peeerr.climbing.exception.constant.ErrorMessage;
import com.peeerr.climbing.exception.ex.ValidationException;
import com.peeerr.climbing.security.CustomUserDetails;
import com.peeerr.climbing.dto.ApiResponse;
import com.peeerr.climbing.constant.ErrorMessage;
import com.peeerr.climbing.exception.ValidationException;
import com.peeerr.climbing.service.FileService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.peeerr.climbing.controller;

import com.peeerr.climbing.config.auth.CustomUserDetails;
import com.peeerr.climbing.dto.common.ApiResponse;
import com.peeerr.climbing.security.CustomUserDetails;
import com.peeerr.climbing.dto.ApiResponse;
import com.peeerr.climbing.service.LikeService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
Expand Down
Loading

0 comments on commit 31e157c

Please sign in to comment.