Skip to content

Commit

Permalink
✨ [Feat] 회원가입 및 로그인 기능 구현
Browse files Browse the repository at this point in the history
✨ [Feat] 회원가입 및 로그인 기능 구현
  • Loading branch information
saokiritoni authored Sep 29, 2024
2 parents 7d349f5 + cbd88f0 commit 6ea3737
Show file tree
Hide file tree
Showing 17 changed files with 504 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ src/main/resources/.env





3 changes: 2 additions & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 109 additions & 1 deletion .idea/dbnavigator.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions .idea/modules/osori.main.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 25 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
plugins {
id 'org.springframework.boot' version '3.1.3'
id 'io.spring.dependency-management' version '1.1.3'
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
id 'java'
}

group = 'osori'
version = '0.0.1-SNAPSHOT'

java {
sourceCompatibility = '17'
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

repositories {
mavenCentral()
}


dependencies {
// Starters
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

// Spring Session
implementation 'org.springframework.session:spring-session-data-redis'

// MySQL Connector
runtimeOnly 'com.mysql:mysql-connector-j'

// Lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

// Testing
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// Swagger
//implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.2.0'
}

test {

tasks.named('test') {
useJUnitPlatform()
}

6 changes: 5 additions & 1 deletion src/main/java/dongguk/osori/OsoriApplication.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package dongguk.osori;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OsoriApplication {
public static void main(String[] args) {

SpringApplication.run(OsoriApplication.class, args);
}
}
80 changes: 80 additions & 0 deletions src/main/java/dongguk/osori/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package dongguk.osori.config;

import lombok.RequiredArgsConstructor;
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.annotation.web.configurers.AbstractHttpConfigurer;
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.session.HttpSessionEventPublisher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.List;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable) // CSRF 비활성화
.formLogin(AbstractHttpConfigurer::disable) // 폼 로그인 비활성화
// 세션 설정
.sessionManagement(session -> session
.sessionFixation().newSession() // 로그인 시 세션 생성
.maximumSessions(1) // 사용자당 최대 세션 수
.maxSessionsPreventsLogin(false) // 초과하면 이전 세션 만료
)
// 권한 설정
.authorizeHttpRequests(authz -> authz
// TODO: 이후 권한 추가해서 수정 필요
.requestMatchers("/api/users/**").permitAll()
//.requestMatchers("/api/users/signup", "/api/users/login", "/api/users/logout").permitAll() // 회원가입, 로그인, 로그아웃은 인증 불필요
//.requestMatchers("/api/**").authenticated() // 그 외 /api/**는 인증 필요
.anyRequest().permitAll() // 그 외 모든 요청은 허용
)
// 로그아웃 설정
.logout(logout -> logout
.logoutUrl("/api/users/logout") // 로그아웃 요청 경로
.logoutSuccessUrl("/api/users/login") // 로그아웃 성공 후 리다이렉트 URL
.invalidateHttpSession(true) // 세션 무효화
.deleteCookies("JSESSIONID") // JSESSIONID 쿠키 삭제
.permitAll() // 로그아웃 요청은 인증 불필요
);
return http.build();
}

// 세션 무효화 처리
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}

// 비밀번호 암호화
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

// CORS 설정 빈 정의
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:3000", "http://localhost:8080")); // 허용할 origin
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 허용할 HTTP 메서드
configuration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type")); // 허용할 HTTP 헤더
configuration.setAllowCredentials(true); // 자격 증명 허용

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 설정 적용
return source;
}
}
35 changes: 35 additions & 0 deletions src/main/java/dongguk/osori/domain/user/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dongguk.osori.domain.user;

import jakarta.persistence.*;
import lombok.*;

@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Getter
@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;

@Column(nullable = false)
private String nickname;

@Column(nullable = false)
private String email;

@Column(nullable = false)
private String password;

public void updateNickName(String nickname) {
this.nickname = nickname;
}
public void updateEmail(String email) {
this.email = email;
}
public void updatePassword(String password) { this.password = password; }

}
Loading

0 comments on commit 6ea3737

Please sign in to comment.