Skip to content

Commit

Permalink
Merge branch 'develop' into feat/#2-InquiryProfile
Browse files Browse the repository at this point in the history
  • Loading branch information
chamcham0707 committed Jun 4, 2024
2 parents bea6d94 + 8d8ad3c commit 518ab37
Show file tree
Hide file tree
Showing 26 changed files with 847 additions and 0 deletions.
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,22 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
implementation 'mysql:mysql-connector-java:8.0.32'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'


// JWT
compileOnly 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'

}

tasks.named('test') {
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.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class OneAndZeroBestApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.sparta.oneandzerobest.auth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class PasswordConfig { // passwordConfigg

@Bean
public PasswordEncoder passwordEncoder() { // passwordEncoder로 빈 등록
//BCrypt: 해시함수: 비밀번호 암호화 -> BCryptPasswordEncoder 암호화
return new BCryptPasswordEncoder(); // PasswordEncoder는 인터페이스로 주입받음 -> BCryptPasswordEncoder구현체


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.sparta.oneandzerobest.auth.config;

import com.sparta.oneandzerobest.auth.filter.JwtAuthenticationFilter;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
/**
* SecurityConfig- Spring Security 설정
*/
public class SecurityConfig {

private final JwtAuthenticationFilter jwtAuthenticationFilter;

public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}

/**
* SecurityFilterChain: 보안 설정을 기반으로 SecurityFilterChain 생성
* @param http : HttpSecurity객체로, CSRF 비활성화, 세션 관리, 요청 권한, 필터 추가
* @return SecurityFilterChain객체 생성(http 요청의 보안 규칙이 적용된)
* @throws Exception
*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf((csrf) -> csrf.disable()); //csrf 비활성화

http.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); // 세션 관리를 stateless설정

// 요청에 대한 권한 설정
http.authorizeHttpRequests(authorizeHttpRequests ->
authorizeHttpRequests
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources 접근 허용 설정
.requestMatchers("/", "/index.html", "/login.html", "/signup.html", "/api/auth/**").permitAll() // 특정 경로 접근 허용
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() // Swagger 접근 허용
.requestMatchers(HttpMethod.GET, "/api/schedules/**").permitAll() // 일정 조회는 모두 허용
.anyRequest().permitAll() // 그 외 모든 요청 접근 허용
//.anyRequest().authenticated() // 그 외 모든 요청 인증처리
);

// jwtAuthenticationFilter의 순서를 지정해주기위해 UsernamePasswordAuthenticationFilter전으로 위치 지정
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.sparta.oneandzerobest.auth.controller;


import com.sparta.oneandzerobest.auth.dto.RefreshTokenRequestDto;
import com.sparta.oneandzerobest.auth.dto.TokenResponseDto;
import com.sparta.oneandzerobest.auth.entity.LoginRequest;
import com.sparta.oneandzerobest.auth.entity.LoginResponse;
import com.sparta.oneandzerobest.auth.entity.SignupRequest;
import com.sparta.oneandzerobest.auth.service.UserService;
import com.sparta.oneandzerobest.auth.util.JwtUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
* 인증기능 컨트롤러
* - 로그인
* - 로그아웃
* - 탈퇴
* - 리프레시 토큰 재발급
*/
@RestController
@RequestMapping("/api/auth")
public class AuthRestController {
private final UserService userService;
private final JwtUtil jwtUtil;

public AuthRestController(UserService userService, JwtUtil jwtUtil) {
this.userService = userService;
this.jwtUtil = jwtUtil;
}

/**
* 회원가입
* @param signupRequest
* @return
*/
@PostMapping("/signup")
public ResponseEntity<String> signup(@RequestBody SignupRequest signupRequest) {
userService.signup(signupRequest);
return ResponseEntity.status(HttpStatus.CREATED).body("회원가입 성공");
}

/**
* 로그인
* @param loginRequest
* @return 헤더에 반환
*/
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody LoginRequest loginRequest) {
LoginResponse tokens = userService.login(loginRequest); // 로그인 시도 및 토큰 생성
String accessToken = tokens.getAccessToken();
String refreshToken = tokens.getRefreshToken();

// 각 토큰을 별도의 헤더에 설정
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + accessToken);
headers.set("Refresh-Token", refreshToken);

return new ResponseEntity<>("로그인 성공", headers, HttpStatus.OK);
}

/**
* 로그아웃
* @param username
* @return
*/
@PostMapping("/logout")
public ResponseEntity<String> logout(@RequestParam String username) {
userService.logout(username);
return ResponseEntity.ok("로그아웃 성공");
}

/**
*withdraw: 탈퇴
* @param username
* @param password
* @return
*/
@PostMapping("/withdraw")
public ResponseEntity<String> withdraw(@RequestParam String username, @RequestParam String password) {
userService.withdraw(username, password);
return ResponseEntity.ok("회원탈퇴 성공");
}

/**
* 리프레시 토큰 재발급
* @param refreshTokenRequestDto
* @return
*/
@PostMapping("/refresh")
public ResponseEntity<TokenResponseDto> refresh(@RequestBody RefreshTokenRequestDto refreshTokenRequestDto) {

String refreshToken = refreshTokenRequestDto.getRefreshToken();
String newAccessToken = jwtUtil.refreshToken(refreshToken);
TokenResponseDto tokenResponseDto = new TokenResponseDto(newAccessToken, refreshToken);
return ResponseEntity.ok(tokenResponseDto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.sparta.oneandzerobest.auth.dto;

import lombok.Getter;

@Getter
public class LoginRequestDto {
private String username;
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.sparta.oneandzerobest.auth.dto;

import lombok.Getter;

@Getter
public class RefreshTokenRequestDto {
private String refreshToken;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sparta.oneandzerobest.auth.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class SignupRequestDto {
private String username;
private String password;
private String name;
private String email;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sparta.oneandzerobest.auth.dto;


import lombok.Getter;

@Getter
public class TokenResponseDto {
private String accessToken;
private String refreshToken;

public TokenResponseDto(String accessToken, String refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sparta.oneandzerobest.auth.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LoginRequest {
private String username;
private String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.sparta.oneandzerobest.auth.entity;


import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class LoginResponse {
private String accessToken;
private String refreshToken;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.sparta.oneandzerobest.auth.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class SignupRequest {
private String username;
private String password;
private String email;
private boolean isAdmin;
private String adminToken;
}
77 changes: 77 additions & 0 deletions src/main/java/com/sparta/oneandzerobest/auth/entity/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.sparta.oneandzerobest.auth.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "users")
public class User implements UserDetails { // Spring Security의 UserDetails
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false, unique = true)
private String username;

@Column(nullable = false)
private String password;

@Column(nullable = false)
private String name;

@Column(nullable = false, unique = true)
private String email;

@Column
private String introduction;

@Column(nullable = false)
private String statusCode;

@Column
private String refreshToken;

@Column
private LocalDateTime statusChangeTime;

@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;

@Column
private LocalDateTime updatedAt;

public User(String username, String password, String name, String email, String statusCode) {
this.username = username;
this.password = password;
this.name = name;
this.email = email;
this.statusCode = statusCode;
this.createdAt = LocalDateTime.now();
}

public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}

public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}

@Override
public boolean isEnabled() {
return "정상".equals(this.statusCode); // 계정이 활성화된 상태인지 확인
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList(); // 권한 관련 설정
}
}
Loading

0 comments on commit 518ab37

Please sign in to comment.