Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat : JWT에 권한을 함께 넣어준다. #80

Merged
merged 15 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions src/main/java/com/prgrms/catchtable/common/Role.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.prgrms.catchtable.common;

import static com.prgrms.catchtable.common.exception.ErrorCode.INVALID_INPUT_TYPE;

import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException;
import java.util.Arrays;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

Expand All @@ -11,4 +15,15 @@ public enum Role {
OWNER("ROLE_OWNER");

private final String role;

public static Role of(String type) {
return Arrays.stream(values())
.filter(role -> role.isEqual(type))
.findAny()
.orElseThrow(() -> new BadRequestCustomException(INVALID_INPUT_TYPE));
}

private boolean isEqual(String input) {
return input.equals(this.role);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@RequiredArgsConstructor
public enum ErrorCode {
NOT_EXIST_MEMBER("존재하지 않는 회원입니다."),
NOT_EXIST_OWNER("존재하지 않는 점주입니다."),
NOT_FOUND_REFRESH_TOKEN("유효하지 않은 RefreshToken입니다."),
TOKEN_EXPIRES("토큰이 만료되었습니다. 다시 로그인 해 주세요."),

Expand All @@ -31,10 +32,9 @@ public enum ErrorCode {
SHOP_NOT_RUNNING("가게가 영업시간이 아닙니다."),
INTERNAL_SERVER_ERROR("내부 서버 오류입니다."),


ALREADY_EXIST_OWNER("이미 존재하는 점주입니다"),
NOT_EXIST_OWNER("해당 아이디의 점주가 존재하지 않습니다."),
BAD_REQUEST_EMAIL_OR_PASSWORD("이메일 혹은 비밀번호를 확인해주세요"),
BAD_REQUEST_INPUT_GENDER_TYPE("성별 타입을 양식대로 입력해주세요");
INVALID_EMAIL_OR_PASSWORD("이메일 혹은 비밀번호를 확인해주세요"),
INVALID_INPUT_TYPE("성별 타입을 양식대로 입력해주세요");

private final String message;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.prgrms.catchtable.jwt.domain;

import static jakarta.persistence.EnumType.STRING;
import static lombok.AccessLevel.PROTECTED;

import com.prgrms.catchtable.common.Role;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -26,10 +29,15 @@ public class RefreshToken {
@Column(name = "email")
private String email;

@Column(name = "role")
@Enumerated(STRING)
private Role role;

@Builder
public RefreshToken(String token, String email) {
public RefreshToken(String token, String email, Role role) {
this.token = token;
this.email = email;
this.role = role;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.prgrms.catchtable.common.exception.ErrorCode.TOKEN_EXPIRES;

import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException;
import com.prgrms.catchtable.jwt.domain.RefreshToken;
import com.prgrms.catchtable.jwt.provider.JwtTokenProvider;
Expand Down Expand Up @@ -48,7 +49,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
RefreshToken refreshTokenEntity = refreshTokenService.getRefreshTokenByToken(
refreshToken);
String email = refreshTokenEntity.getEmail();
Token newToken = jwtTokenProvider.createToken(email);
Role role = refreshTokenEntity.getRole();
Token newToken = jwtTokenProvider.createToken(email, role);

((HttpServletResponse) response).setHeader("AccessToken",
newToken.getAccessToken());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.prgrms.catchtable.jwt.provider;


import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.jwt.config.JwtConfig;
import com.prgrms.catchtable.jwt.service.JwtUserDetailsService;
import com.prgrms.catchtable.jwt.token.Token;
Expand All @@ -20,18 +21,19 @@
public class JwtTokenProvider {

private final JwtConfig jwtConfig;

private final JwtUserDetailsService jwtUserDetailsService;
private final String JWT_ROLE = "ROLE";

public Token createToken(String email) {
public Token createToken(String email, Role role) {

Claims claims = Jwts.claims().setSubject(email);
claims.put(JWT_ROLE, role.getRole());
Date now = new Date();

String accessToken = createAccessToken(claims, now);
String refreshToken = createRefreshToken(claims, now);

return new Token(accessToken, refreshToken, email);
return new Token(accessToken, refreshToken, email, role);
}

private String createAccessToken(Claims claims, Date now) {
Expand Down Expand Up @@ -73,7 +75,9 @@ public boolean validateToken(String token) {

public Authentication getAuthentication(String token) {
String email = getEmail(token);
UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(email);
Role role = getRole(token);

UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(email, role);
return new UsernamePasswordAuthenticationToken(userDetails, "",
userDetails.getAuthorities());
}
Expand All @@ -87,4 +91,16 @@ private String getEmail(String token) {

return claims.getSubject();
}

private Role getRole(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(jwtConfig.getClientSecret())
.build()
.parseClaimsJws(token)
.getBody();

String role = (String) claims.get(JWT_ROLE);

return Role.of(role);
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
package com.prgrms.catchtable.jwt.service;

import static com.prgrms.catchtable.common.exception.ErrorCode.NOT_EXIST_MEMBER;
import static com.prgrms.catchtable.common.exception.ErrorCode.NOT_EXIST_OWNER;

import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.common.exception.custom.NotFoundCustomException;
import com.prgrms.catchtable.member.repository.MemberRepository;
import com.prgrms.catchtable.owner.repository.OwnerRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class JwtUserDetailsService implements UserDetailsService {
public class JwtUserDetailsService {

private final MemberRepository memberRepository;
private final OwnerRepository ownerRepository;

@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return memberRepository.findMemberByEmail(email)
.orElseThrow(() -> new NotFoundCustomException(NOT_EXIST_MEMBER));
public UserDetails loadUserByUsername(String email, Role role)
throws UsernameNotFoundException {

if (role.equals(Role.MEMBER)) {
return memberRepository.findMemberByEmail(email)
.orElseThrow(() -> new NotFoundCustomException(NOT_EXIST_MEMBER));
} else {
return ownerRepository.findOwnerByEmail(email)
.orElseThrow(() -> new NotFoundCustomException(NOT_EXIST_OWNER));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.prgrms.catchtable.common.exception.ErrorCode.NOT_FOUND_REFRESH_TOKEN;

import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.common.exception.custom.NotFoundCustomException;
import com.prgrms.catchtable.jwt.domain.RefreshToken;
import com.prgrms.catchtable.jwt.repository.RefreshTokenRepository;
Expand All @@ -19,6 +20,7 @@ public class RefreshTokenService {
@Transactional
public void saveRefreshToken(Token totalToken) {
String email = totalToken.getEmail();
Role role = totalToken.getRole();

if (refreshTokenRepository.existsRefreshTokenByEmail(email)) {
refreshTokenRepository.deleteRefreshTokenByEmail(email);
Expand All @@ -27,6 +29,7 @@ public void saveRefreshToken(Token totalToken) {
RefreshToken newRefreshToken = RefreshToken.builder()
.token(totalToken.getRefreshToken())
.email(email)
.role(role)
.build();

refreshTokenRepository.save(newRefreshToken);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/prgrms/catchtable/jwt/token/Token.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.prgrms.catchtable.jwt.token;

import com.prgrms.catchtable.common.Role;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -12,4 +13,6 @@ public class Token {
private String refreshToken;

private String email;

private Role role;
}
4 changes: 2 additions & 2 deletions src/main/java/com/prgrms/catchtable/member/domain/Gender.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.prgrms.catchtable.member.domain;

import static com.prgrms.catchtable.common.exception.ErrorCode.BAD_REQUEST_INPUT_GENDER_TYPE;
import static com.prgrms.catchtable.common.exception.ErrorCode.INVALID_INPUT_TYPE;

import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException;
import java.util.Arrays;
Expand All @@ -19,7 +19,7 @@ public static Gender of(String input) {
return Arrays.stream(values())
.filter(gender -> gender.isEqual(input))
.findAny()
.orElseThrow(() -> new BadRequestCustomException(BAD_REQUEST_INPUT_GENDER_TYPE));
.orElseThrow(() -> new BadRequestCustomException(INVALID_INPUT_TYPE));
}

private boolean isEqual(String input) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.prgrms.catchtable.member.service;

import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.jwt.provider.JwtTokenProvider;
import com.prgrms.catchtable.jwt.service.RefreshTokenService;
import com.prgrms.catchtable.jwt.token.Token;
Expand All @@ -17,10 +18,8 @@
public class MemberService {

private final MemberRepository memberRepository;

private final JwtTokenProvider jwtTokenProvider;

private final RefreshTokenService refreshTokenService;
private final JwtTokenProvider jwtTokenProvider;

@Transactional
public Token oauthLogin(OAuthAttribute attributes) {
Expand All @@ -36,7 +35,7 @@ public Token oauthLogin(OAuthAttribute attributes) {
}

private Token createTotalToken(String email) {
Token totalToken = jwtTokenProvider.createToken(email);
Token totalToken = jwtTokenProvider.createToken(email, Role.MEMBER);
refreshTokenService.saveRefreshToken(totalToken);
return totalToken;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.prgrms.catchtable.owner.service;

import static com.prgrms.catchtable.common.exception.ErrorCode.ALREADY_EXIST_OWNER;
import static com.prgrms.catchtable.common.exception.ErrorCode.BAD_REQUEST_EMAIL_OR_PASSWORD;
import static com.prgrms.catchtable.common.exception.ErrorCode.INVALID_EMAIL_OR_PASSWORD;

import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.common.exception.custom.BadRequestCustomException;
import com.prgrms.catchtable.jwt.provider.JwtTokenProvider;
import com.prgrms.catchtable.jwt.service.RefreshTokenService;
import com.prgrms.catchtable.jwt.token.Token;
import com.prgrms.catchtable.member.domain.Gender;
import com.prgrms.catchtable.owner.domain.Owner;
Expand All @@ -16,6 +18,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
Expand All @@ -24,7 +27,9 @@ public class OwnerService {
private final OwnerRepository ownerRepository;
private final PasswordEncoder passwordEncoder;
private final JwtTokenProvider jwtTokenProvider;
private final RefreshTokenService refreshTokenService;

@Transactional
public JoinOwnerResponse joinOwner(JoinOwnerRequest joinOwnerRequest) {

//이미 존재하는 이메일이라면
Expand All @@ -47,22 +52,29 @@ private void validateExistsOwner(JoinOwnerRequest joinOwnerRequest) {
}
}

@Transactional
public Token loginOwner(LoginOwnerRequest loginRequest) {

//email 확인
Owner loginOwner = ownerRepository.findOwnerByEmail(loginRequest.email())
.orElseThrow(() -> new BadRequestCustomException(BAD_REQUEST_EMAIL_OR_PASSWORD));
.orElseThrow(() -> new BadRequestCustomException(INVALID_EMAIL_OR_PASSWORD));

//password 확인
validatePassword(loginRequest, loginOwner);

return jwtTokenProvider.createToken(loginOwner.getEmail());
return createTotalToken(loginOwner.getEmail());
}

private void validatePassword(LoginOwnerRequest loginRequest, Owner loginOwner) {
if (!passwordEncoder.matches(loginRequest.password(), loginOwner.getPassword())) {
throw new BadRequestCustomException(BAD_REQUEST_EMAIL_OR_PASSWORD);
throw new BadRequestCustomException(INVALID_EMAIL_OR_PASSWORD);
}
}

private Token createTotalToken(String email) {
Token totalToken = jwtTokenProvider.createToken(email, Role.OWNER);
refreshTokenService.saveRefreshToken(totalToken);
return totalToken;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import com.prgrms.catchtable.common.Role;
import com.prgrms.catchtable.jwt.config.JwtConfig;
import com.prgrms.catchtable.jwt.service.JwtUserDetailsService;
import com.prgrms.catchtable.jwt.token.Token;
Expand Down Expand Up @@ -34,7 +35,7 @@ void validToken() {
when(config.getClientSecret()).thenReturn(clientKey);
when(config.getExpiryMinute()).thenReturn(1);
when(config.getExpiryMinuteRefresh()).thenReturn(1);
Token token = jwtTokenProvider.createToken(email);
Token token = jwtTokenProvider.createToken(email, Role.MEMBER);

//then
assertThat(jwtTokenProvider.validateToken(token.getAccessToken())).isTrue();
Expand All @@ -48,7 +49,7 @@ void invalidToken() {
when(config.getClientSecret()).thenReturn(clientKey);
when(config.getExpiryMinute()).thenReturn(0);
when(config.getExpiryMinuteRefresh()).thenReturn(0);
Token token = jwtTokenProvider.createToken(email);
Token token = jwtTokenProvider.createToken(email, Role.OWNER);

//then
assertThat(jwtTokenProvider.validateToken(token.getAccessToken())).isFalse();
Expand All @@ -65,9 +66,9 @@ void getAuthenticationTest() {
when(config.getClientSecret()).thenReturn(clientKey);
when(config.getExpiryMinute()).thenReturn(1);
when(config.getExpiryMinuteRefresh()).thenReturn(1);
Token token = jwtTokenProvider.createToken(email);
Token token = jwtTokenProvider.createToken(email, Role.MEMBER);

when(jwtUserDetailsService.loadUserByUsername(email))
when(jwtUserDetailsService.loadUserByUsername(email, Role.MEMBER))
.thenReturn(member);

//then
Expand Down
Loading