Skip to content

Commit

Permalink
Merge pull request #38 from codestates-seb/dev-Member/Security
Browse files Browse the repository at this point in the history
PR: 자체 회원 가입 및 이메일 인증 기능 구현
  • Loading branch information
rkddnr05 authored Sep 4, 2023
2 parents 5dc7fa6 + a1a772e commit 085875a
Show file tree
Hide file tree
Showing 37 changed files with 1,240 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .idea/.gitignore

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

16 changes: 16 additions & 0 deletions .idea/compiler.xml

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

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

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

20 changes: 20 additions & 0 deletions .idea/jarRepositories.xml

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

7 changes: 7 additions & 0 deletions .idea/misc.xml

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

9 changes: 9 additions & 0 deletions .idea/modules.xml

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

8 changes: 8 additions & 0 deletions .idea/modules/008main_project.main.iml

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

9 changes: 9 additions & 0 deletions .idea/seb45_main_008.iml

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

124 changes: 124 additions & 0 deletions .idea/uiDesigner.xml

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

6 changes: 6 additions & 0 deletions .idea/vcs.xml

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

17 changes: 14 additions & 3 deletions server/008main_project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,24 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
implementation 'org.mapstruct:mapstruct:1.5.5.Final' //버전 수정
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' //추가
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// security 작업을 위한 의존성
implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.0' //mail 전송을 위한 추가
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'com.google.code.gson:gson:2.8.8' // gson 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.stockholm.main_project.auth.erroesponse;

import lombok.Getter;
import lombok.Setter;
import org.springframework.http.HttpStatus;

@Getter
@Setter
public class ErrorResponse {
private int status;
private String error;
private String message;

public static ErrorResponse of(HttpStatus httpStatus) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setStatus(httpStatus.value());
errorResponse.setError(httpStatus.getReasonPhrase());
errorResponse.setMessage("Authentication failed");
return errorResponse;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.stockholm.main_project.auth.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.stockholm.main_project.auth.jwt.JwtTokenizer;
import com.stockholm.main_project.auth.logindto.LoginDto;
import com.stockholm.main_project.member.entity.Member;
import lombok.SneakyThrows;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final JwtTokenizer jwtTokenizer;

public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtTokenizer jwtTokenizer) {
this.authenticationManager = authenticationManager;
this.jwtTokenizer = jwtTokenizer;
}

@SneakyThrows
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
ObjectMapper objectMapper = new ObjectMapper();
LoginDto loginDto = objectMapper.readValue(request.getInputStream(), LoginDto.class);
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(loginDto.getEmail(), loginDto.getPassword());

return authenticationManager.authenticate(authenticationToken);
}

@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws ServletException, IOException {
Member member = (Member) authResult.getPrincipal();

String accessToken = delegateAccessToken(member);
String refreshToken = delegateRefreshToken(member);

response.setHeader("Authorization", "Bearer " + accessToken);
response.setHeader("Refresh", refreshToken);
//response.setHeader("Access-Control-Expose-Headers", "Authorization");
//response.addHeader("Access-Control-Expose-Headers", "MemberId");

this.getSuccessHandler().onAuthenticationSuccess(request, response, authResult);
}


private String delegateAccessToken(Member member) {
Map<String, Object> claims = new HashMap<>();
claims.put("memberEmail", member.getEmail());
claims.put("roles", member.getRoles());

String subject = member.getEmail();
Date expiration = jwtTokenizer.getTokenExpiration(jwtTokenizer.getAccessTokenExpirationMinutes());

String base64EncodedSecretKey = jwtTokenizer.encodeBase64SecretKey(jwtTokenizer.getSecretKey());

String accessToken = jwtTokenizer.generateAccessToken(claims, subject, expiration, base64EncodedSecretKey);

return accessToken;
}

private String delegateRefreshToken(Member member) {
String subject = member.getEmail();
Date expiration = jwtTokenizer.getTokenExpiration(jwtTokenizer.getRefreshTokenExpirationMinutes());
String base64EncodedSecretKey = jwtTokenizer.encodeBase64SecretKey(jwtTokenizer.getSecretKey());

String refreshToken = jwtTokenizer.generateRefreshToken(subject, expiration, base64EncodedSecretKey);

return refreshToken;
}
}
Loading

0 comments on commit 085875a

Please sign in to comment.