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

add #12

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

add #12

wants to merge 2 commits into from

Conversation

paragon0107
Copy link
Contributor

@paragon0107 paragon0107 commented Jun 2, 2024

UserJoinResponse

public record UserJoinResponse(
String accessToken,
String refreshToken,
String userId
) {
public static UserJoinResponse of(
String accessToken,
String refreshToken,
String userId
) {
return new UserJoinResponse(accessToken, refreshToken,userId);
}
}

refreshToken 추가

JwtTokenProvider

private static final Long ACCESS_TOKEN_EXPIRATION_TIME = 5 * 60 * 1000L;
private static final Long REFRESH_TOKEN_EXPIRATION_TIME = 24 * 60 * 60 * 1000L * 14;
@Value("${jwt.secret}")
private String JWT_SECRET;
public String issueAccessToken(final Authentication authentication) {
return generateToken(authentication, ACCESS_TOKEN_EXPIRATION_TIME);
}
public String issueRefreshToken(final Authentication authentication) {
return generateToken(authentication, REFRESH_TOKEN_EXPIRATION_TIME);
}
public TokenDto createAllToken(UserAuthentication authentication){
return TokenDto.of(issueAccessToken(authentication),issueRefreshToken(authentication));
}

refreshToken시간 추가, refreshToken생성 메서드 추가,refreshToken생성,accessToken 생성 호출 메서드 추가

AuthController

@RestController
@RequestMapping("/api/v1/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
@PostMapping("/login")
public ResponseEntity<UserJoinResponse> LoginMember(
@RequestBody String name
) {
UserJoinResponse userJoinResponse = authService.login(name);
return ResponseEntity.status(HttpStatus.CREATED)
.header("Location", userJoinResponse.userId())
.body(
userJoinResponse
);
}
@PostMapping("/reissue")
public ResponseEntity<UserJoinResponse> reissue(
HttpServletRequest request
){
UserJoinResponse userJoinResponse = authService.reissue(request);
return ResponseEntity.status(HttpStatus.CREATED)
.header("Location", userJoinResponse.userId())
.body(
userJoinResponse
);
}
}

로그인, 리프레쉬 토큰 재생성 컨트롤러

MemberService

@Transactional
public UserJoinResponse createMember(
MemberCreateDto memberCreate
) {
Member member = memberRepository.save(
Member.create(memberCreate.name(), memberCreate.part(), memberCreate.age())
);
TokenDto tokenDto = authService.generateToken(member);
return UserJoinResponse.of(tokenDto.accessToken(), tokenDto.refreshToken(),member.getId().toString());
}

멤버 생성 및 토큰 발급 기능

AuthService

@Service
@RequiredArgsConstructor
public class AuthService {
private final JwtTokenProvider jwtTokenProvider;
private final MemberRepository memberRepository;
private final RedisTokenRepository redisTokenRepository;
@Transactional
public UserJoinResponse login(String name){
System.out.println(name);
Member member = memberRepository.findMemberByName(name).orElseThrow(
() -> new RuntimeException("Not found Account")
);
TokenDto tokenDto = generateToken(member);
return UserJoinResponse.of(tokenDto.accessToken(), tokenDto.refreshToken(),member.getId().toString());
}
@Transactional
public TokenDto generateToken(Member member){
UserAuthentication userAuthentication = UserAuthentication.createUserAuthentication(member.getId());
TokenDto tokenDto = jwtTokenProvider.createAllToken(userAuthentication);
redisTokenRepository.save(Token.builder().id(member.getId()).refreshToken(tokenDto.refreshToken()).build());
return tokenDto;
}
@Transactional
public UserJoinResponse reissue(HttpServletRequest request){
String refreshToken = getRefreshFromRequest(request);
if(refreshToken == null){
throw new UnauthorizedException(ErrorMessage.JWT_UNAUTHORIZED_EXCEPTION);
}
if(jwtTokenProvider.validateToken(refreshToken)==VALID_JWT){
Long memberId = jwtTokenProvider.getUserFromJwt(refreshToken);
Token token = redisTokenRepository.findById(memberId).orElseThrow(
() -> new RuntimeException("refresh token 만료 혹은 없음")
);
UserAuthentication authentication = UserAuthentication.createUserAuthentication(memberId);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
return UserJoinResponse.of(jwtTokenProvider.issueAccessToken(authentication), refreshToken,memberId.toString());
}
throw new UnauthorizedException(ErrorMessage.JWT_NOT_FOUND_TOKEN);
}
public String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring("Bearer ".length());
}
return null;
}
private String getRefreshFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Param");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring("Bearer ".length());
}
return null;
}
}

  • 로그인 및 토큰 발급하는 login 메서드,
  • Access/Refresh Token 발급해주는 generateToeken메서드
  • 엑세스 토큰 재발급 해주는 reissue메서드
  • getJwt/RefreshToken메서드: 원래 필터에 있었지만, 필터는 정말 필터의 기능만 하고 기타 기능은 다른데로 옮기는게 좋을것 같기도 했고 다른곳에서 쓰일 수도 있을것 같아서 service단으로 옮김

궁금한점

try {
final String token = authService.getJwtFromRequest(request);
if (jwtTokenProvider.validateToken(token) == VALID_JWT ) {
Long memberId = jwtTokenProvider.getUserFromJwt(token);
UserAuthentication authentication = UserAuthentication.createUserAuthentication(memberId);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}

  • 여기에 시큐리티 컨텍스트 홀더에 저장하는 일을 필터에서 해주니까 따로 토큰 발급할 때 해줄 필요가 없을까요?

UserAuthentication authentication = UserAuthentication.createUserAuthentication(memberId);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

  • authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 이 부분을 reissue에서 토큰생성할 때는 넣어줬고 로그인할 때는 이 코드를 안넣어줬는데 토큰 생성시에 차이가 있는지? or 통일하는게 나은지?? 궁금합니당

  • reIssue할 때 리프레쉬 토큰도 한번 더 업데이트 해줘야 하는건지 아니면 로그인할 때만 업데이트를 해주는건지 궁금해요

@paragon0107 paragon0107 linked an issue Jun 2, 2024 that may be closed by this pull request
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6주차 실습과제
1 participant