Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c3be2a1
Create README.md
sujeong11 Jan 18, 2023
24c2bf3
chore: 스프링부트와 자바 버전 변경
sujeong11 Jan 25, 2023
af7b00c
feat: 프로젝트 설정 추가
sujeong11 Jan 27, 2023
e3a7446
docs: ERD 설계
sujeong11 Jan 27, 2023
bbf68c9
feat: User 엔티티 생성
sujeong11 Jan 27, 2023
3be625f
feat: JPA Auditing을 활용한 BaseTimeEntity 생성
sujeong11 Jan 27, 2023
12b4691
feat: 기본 Security 설정 추가
sujeong11 Jan 27, 2023
305e8e0
feat: User 레포지토리 생성
sujeong11 Jan 27, 2023
ab11428
feat: 회원가입 API 및 validation 의존성 추가
sujeong11 Jan 28, 2023
f053e40
chore: jwt 관련 라이브러리 추가
sujeong11 Jan 28, 2023
e518121
feat: Spring Security & JWT 구현
sujeong11 Jan 29, 2023
89d7814
feat: 로그인 API
sujeong11 Jan 29, 2023
867f3ec
feat: JWT 에러 핸들러
sujeong11 Jan 29, 2023
c7c4a1e
feat: API 성공/에러 응답 데이터 정의
sujeong11 Jan 29, 2023
eb354a2
feat: Exception 처리 환경
sujeong11 Jan 29, 2023
f38d8f4
fix: secretKey를 yml에서 주입받아 사용하도록 수정
sujeong11 Jan 29, 2023
0ef5b83
refactor: 폴더 구조 및 변수명
sujeong11 Feb 1, 2023
13c9bb0
fix: UserService의 회원가입 Dto를 반환
sujeong11 Feb 1, 2023
30d1ff5
docs: swagger 설정
sujeong11 Feb 1, 2023
668830a
docs: jwt를 위한 swagger 설정
sujeong11 Feb 1, 2023
ad4490a
docs: 회원 API swagger 문서화 작성
sujeong11 Feb 1, 2023
527be4d
feat: Point, Image 엔티티 생성
sujeong11 Feb 1, 2023
e2f03dd
chore: application.yml gitignore에 추가
sujeong11 Feb 2, 2023
b9bd9b5
feat: AWS S3 다중 업로드
sujeong11 Feb 3, 2023
acb0b96
feat: 상품 등록 API 및 문서화
sujeong11 Feb 3, 2023
f1d2279
docs: ERD 수정
sujeong11 Feb 4, 2023
557bab7
feat: Like 엔티티 생성
sujeong11 Feb 4, 2023
f63e2ce
feat: 좋아요 추가/취소 API
sujeong11 Feb 5, 2023
be9d377
feat: 인터셉터 구현
sujeong11 Feb 5, 2023
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ bin/
out/
!**/src/main/**/out/
!**/src/test/**/out/
application.yml

### NetBeans ###
/nbproject/private/
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Spring-JPA-study
22 changes: 19 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.1'
id 'io.spring.dependency-management' version '1.1.0'
id 'org.springframework.boot' version '2.7.8'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.dku'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
sourceCompatibility = '11'

configurations {
compileOnly {
Expand All @@ -27,6 +27,22 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'

// Jwt
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'

// Http
implementation 'org.apache.httpcomponents:httpclient:4.5.7'

// Swagger
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'io.springfox:springfox-swagger-ui:3.0.0'

// AWS S3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
}

tasks.named('test') {
Expand Down
Binary file added document/ERD.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified gradlew
100755 → 100644
Empty file.
182 changes: 91 additions & 91 deletions gradlew.bat
Original file line number Diff line number Diff line change
@@ -1,91 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*

:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega
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.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class SpringStudyApplication {

Expand Down
20 changes: 20 additions & 0 deletions src/main/java/com/dku/springstudy/config/InterceptorConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.dku.springstudy.config;

import com.dku.springstudy.dto.common.interceptor.HttpInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@RequiredArgsConstructor
public class InterceptorConfig implements WebMvcConfigurer {

private final HttpInterceptor httpInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(httpInterceptor) // 만든 인터셉터 등록
.addPathPatterns("/**");
}
}
57 changes: 57 additions & 0 deletions src/main/java/com/dku/springstudy/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.dku.springstudy.config;

import com.dku.springstudy.security.jwt.JwtAuthenticationFilter;
import com.dku.springstudy.security.jwt.JwtTokenProvider;
import com.dku.springstudy.security.exception.JwtAccessDeniedHandler;
import com.dku.springstudy.security.exception.JwtAuthenticationEntryPoint;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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;

@Slf4j
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

private final JwtTokenProvider jwtTokenProvider;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

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

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 세션 사용 X
.and()
.authorizeRequests()
.antMatchers("/api/sign-up", "/api/login").permitAll()
.antMatchers("/v3/api-docs/**", "/swagger*/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.usernameParameter("email") // 식별 데이터를 email로 사용
.and()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
.and()
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);

return http.build();
}
}
61 changes: 61 additions & 0 deletions src/main/java/com/dku/springstudy/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.dku.springstudy.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.Arrays;
import java.util.List;

@Configuration
public class SwaggerConfig {

@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.ignoredParameterTypes(AuthenticationPrincipal.class)
.securityContexts(Arrays.asList(securityContext()))
.securitySchemes(Arrays.asList(apiKey()))
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.dku.springstudy.controller"))
.paths(PathSelectors.ant("/api/**"))
.build();
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("D-coding 당근마켓 클론 API")
.description("당근마켓 클론 API 명세서")
.version("v0.0.1")
.build();
}

private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.build();
}

private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
}

private ApiKey apiKey() {
return new ApiKey("Authorization", "Authorization", "header");
}
}
Loading