Skip to content

Commit

Permalink
Merge pull request #171 from daadaadaah/refactor/user-authhelper-for-…
Browse files Browse the repository at this point in the history
…code-flexibility

`의존성 주입`을 활용하여 코드 유연성 향상
  • Loading branch information
daadaadaah authored Aug 22, 2023
2 parents 11a382d + a302d60 commit bf1ccad
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 184 deletions.
21 changes: 21 additions & 0 deletions src/main/java/com/hcommerce/heecommerce/auth/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.hcommerce.heecommerce.auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AuthConfig {

private final JwtAuthHelper jwtAuthHelper;

@Autowired
public AuthConfig(JwtAuthHelper jwtAuthHelper) {
this.jwtAuthHelper = jwtAuthHelper;
}

@Bean
public AuthHelper authHelper() {
return jwtAuthHelper; // TODO : 추후에 세션으로 관리하는 걸로 바뀌면 이곳 수정해줘야 함.
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/hcommerce/heecommerce/auth/AuthHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.hcommerce.heecommerce.auth;

import com.hcommerce.heecommerce.user.UserQueryRepository;
import jakarta.servlet.http.HttpServletRequest;

public interface AuthHelper {

boolean isAuthenticatedUser(HttpServletRequest request, UserQueryRepository userQueryRepository);

AuthUserInfo getAuthUserInfo(String authInfo);
}
Original file line number Diff line number Diff line change
@@ -1,118 +1,50 @@
package com.hcommerce.heecommerce.auth;

import com.hcommerce.heecommerce.common.utils.JwtUtils;
import com.hcommerce.heecommerce.user.UserQueryRepository;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


/**
* AuthHelper
* - isAuthenticatedUser
* - getAuthUserInfo
*
* JwtAuthHelper
*
* SessionAuthHelper
*
*/
@Service
public class AuthenticationService {

private final String AUTH_TYPE = "Bearer";

private final JwtUtils jwtUtils;

private final UserQueryRepository userQueryRepository;

private final AuthHelper authHelper;

@Autowired
public AuthenticationService(JwtUtils jwtUtils, UserQueryRepository userQueryRepository) {
this.jwtUtils = jwtUtils;
public AuthenticationService(
UserQueryRepository userQueryRepository,
AuthHelper authHelper
) {
this.userQueryRepository = userQueryRepository;
}

// TODO : 테스트용으로 일단 간단하게 구현함.
public String login(int userId) {
return jwtUtils.encode(userId);
this.authHelper = authHelper;
}

/**
* isAuthenticatedUser는 HTTP 요청이 인증된 사용자에 의한 것인지를 판단하는 함수이다.
*/
public boolean isAuthenticatedUser(HttpServletRequest request) {
String authorization = request.getHeader("Authorization");

if(authorization == null || authorization.isBlank()) {
return false;
}

if(!isValidAuthType(authorization)) {
return false;
}

String accessToken = extractAccessToken(authorization);

if(accessToken == null || accessToken.isBlank()) {
return false;
}

AuthUserInfo authUserInfo = parseAccessToken(accessToken);

if(authUserInfo == null) {
return false;
}

boolean hasUserId = userQueryRepository.hasUserId(authUserInfo.getUserId());

if(!hasUserId) {
return false;
}

return true;
return authHelper.isAuthenticatedUser(request, userQueryRepository);
}

/**
* parseAuthorization는 HTTP Header 의 authorization 를 피상해서 accessToken에 담긴 정보를 리턴하는 함수이다.
* 각 단계별로 유효성 검사를 할 수 있겠지만, 다른 기능 구현에 집중하기 위해 시간 관계상
* AuthInterceptor 에서 authorization 의 유효성이 모두 유효하게 판단된 상황을 가정해서 따로 추가하지 않았다.
*/
public AuthUserInfo parseAuthorization(String authorization) {
String accessToken = extractAccessToken(authorization);

AuthUserInfo authUserInfo = parseAccessToken(accessToken);

return authUserInfo;
}

/**
* isValidAuthType 는 HTTP Header 의 authorization 의 인증 유형이 유효한 인증 유형인지를 판단하는 함수이다.
*/
private boolean isValidAuthType(String authorization) {
return authorization.startsWith(AUTH_TYPE);
}

/**
* isValidAuthType 는 HTTP Header 의 authorization로부터 accessToken을 추춣하는 함수이다.
*/
private String extractAccessToken(String authorization) {
String[] authorizationUnit = authorization.split(AUTH_TYPE+" ");

if(authorizationUnit.length < 2) {
return null;
}

String accessToken = authorizationUnit[1];

if(accessToken.isBlank()) {
return null;
}

return accessToken;
}

/**
* parseAccessToken 는 accessToken에 파싱하여 저장된 사용자 인증 정보를 리턴하는 함수이다.
*/
private AuthUserInfo parseAccessToken(String accessToken) {
Claims claims = jwtUtils.decode(accessToken);

if(claims == null) {
return null;
}

int userId = claims.get("userId", Integer.class);

return new AuthUserInfo(userId);
public AuthUserInfo getAuthUserInfo(String authInfo) {
return authHelper.getAuthUserInfo(authInfo);
}
}
113 changes: 113 additions & 0 deletions src/main/java/com/hcommerce/heecommerce/auth/JwtAuthHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.hcommerce.heecommerce.auth;

import com.hcommerce.heecommerce.common.utils.JwtUtils;
import com.hcommerce.heecommerce.user.UserQueryRepository;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class JwtAuthHelper implements AuthHelper {

private final String AUTH_TYPE = "Bearer";

private final JwtUtils jwtUtils;

@Autowired
public JwtAuthHelper(JwtUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}


/**
* isAuthenticatedUser는 HTTP 요청이 인증된 사용자에 의한 것인지를 판단하는 함수이다.
*/
@Override
public boolean isAuthenticatedUser(HttpServletRequest request, UserQueryRepository userQueryRepository) {
String authorization = request.getHeader("Authorization");

if(authorization == null || authorization.isBlank()) {
return false;
}

if(!isValidAuthType(authorization)) {
return false;
}

String accessToken = extractAccessToken(authorization);

if(accessToken == null || accessToken.isBlank()) {
return false;
}

AuthUserInfo authUserInfo = parseAccessToken(accessToken);

if(authUserInfo == null) {
return false;
}

boolean hasUserId = userQueryRepository.hasUserId(authUserInfo.getUserId());

if(!hasUserId) {
return false;
}

return true;
}

/**
* getAuthUserInfo 는 HTTP Header 의 authorization 를 피상해서 accessToken에 담긴 정보를 리턴하는 함수이다.
* 각 단계별로 유효성 검사를 할 수 있겠지만, 다른 기능 구현에 집중하기 위해 시간 관계상
* AuthInterceptor 에서 authorization 의 유효성이 모두 유효하게 판단된 상황을 가정해서 따로 추가하지 않았다.
*/
@Override
public AuthUserInfo getAuthUserInfo(String auth) {
String accessToken = extractAccessToken(auth);

AuthUserInfo authUserInfo = parseAccessToken(accessToken);

return authUserInfo;
}

/**
* isValidAuthType 는 HTTP Header 의 authorization 의 인증 유형이 유효한 인증 유형인지를 판단하는 함수이다.
*/
private boolean isValidAuthType(String authorization) {
return authorization.startsWith(AUTH_TYPE);
}

/**
* isValidAuthType 는 HTTP Header 의 authorization로부터 accessToken을 추춣하는 함수이다.
*/
private String extractAccessToken(String authorization) {
String[] authorizationUnit = authorization.split(AUTH_TYPE+" ");

if(authorizationUnit.length < 2) {
return null;
}

String accessToken = authorizationUnit[1];

if(accessToken.isBlank()) {
return null;
}

return accessToken;
}

/**
* parseAccessToken 는 accessToken에 파싱하여 저장된 사용자 인증 정보를 리턴하는 함수이다.
*/
private AuthUserInfo parseAccessToken(String accessToken) {
Claims claims = jwtUtils.decode(accessToken);

if(claims == null) {
return null;
}

int userId = claims.get("userId", Integer.class);

return new AuthUserInfo(userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public ResponseDto placeOrderInAdvance(
@RequestHeader(value = "Authorization") String authorization,
@Valid @RequestBody OrderFormDto orderFormDto
) {
AuthUserInfo authUserInfo = authenticationService.parseAuthorization(authorization);
AuthUserInfo authUserInfo = authenticationService.getAuthUserInfo(authorization);

OrderForm orderForm = OrderForm.of(orderFormDto, authUserInfo.getUserId());

Expand Down
Loading

0 comments on commit bf1ccad

Please sign in to comment.