From 9ea8927a882f360b05f8a15fb66a2c90a36a7b6d Mon Sep 17 00:00:00 2001 From: ahah525 Date: Wed, 9 Nov 2022 17:20:14 +0900 Subject: [PATCH] =?UTF-8?q?#37=20-=20Feat:=20JWT=20AccessToken=20=ED=99=94?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=A0=81=EC=9A=A9(2=EC=B0=A8=20=ED=99=94=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EA=B2=80=EC=A6=9D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mutbooks/app/member/entity/Member.java | 4 ++++ .../app/member/service/MemberService.java | 21 ++++++++++++++++--- .../filter/JwtAuthorizationFilter.java | 9 +++++--- .../app/security/jwt/JwtProvider.java | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/entity/Member.java b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/entity/Member.java index f5a3f37..a2ea20e 100644 --- a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/entity/Member.java +++ b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/entity/Member.java @@ -35,6 +35,10 @@ public class Member extends BaseEntity { private int restCash; // 예치금 + // accessToken + @Column(columnDefinition = "TEXT") + private String accessToken; + // Member 의 memberExtra 에 값이 저장될 때, MemberExtra 도 같이 저장되도록 @OneToOne(mappedBy = "member", cascade = CascadeType.ALL) private MemberExtra memberExtra; diff --git a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/service/MemberService.java b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/service/MemberService.java index 0cbbfa5..92c99b0 100644 --- a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/service/MemberService.java +++ b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/member/service/MemberService.java @@ -1,6 +1,5 @@ package com.example.mutbooks.app.member.service; -import com.example.mutbooks.app.security.dto.MemberContext; import com.example.mutbooks.app.cash.entity.CashLog; import com.example.mutbooks.app.cash.service.CashService; import com.example.mutbooks.app.mail.service.MailService; @@ -13,6 +12,7 @@ import com.example.mutbooks.app.member.form.PwdModifyForm; import com.example.mutbooks.app.member.form.WithdrawAccountForm; import com.example.mutbooks.app.member.repository.MemberRepository; +import com.example.mutbooks.app.security.dto.MemberContext; import com.example.mutbooks.app.security.jwt.JwtProvider; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -21,6 +21,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import java.util.Map; import java.util.UUID; @@ -161,10 +162,24 @@ public void createBankInfo(Member member, WithdrawAccountForm withDrawAccountFor //forceAuthentication(member); } + // AccessToken 발급(발급된게 있으면 바로 리턴) + @Transactional public String genAccessToken(Member member) { - Map claims = member.getAccessTokenClaims(); - String accessToken = jwtProvider.generateAccessToken(claims, 60 * 60 * 24 * 90); // 유효기간 90일 + // 1. DB에서 AccessToken 조회 + String accessToken = member.getAccessToken(); + // 2. 만료시, 토큰 새로 발급 + if (StringUtils.hasLength(accessToken) == false) { + // 지금으로부터 100년간의 유효기간을 가지는 토큰을 생성, DB에 토큰 저장 + Map claims = member.getAccessTokenClaims(); + accessToken = jwtProvider.generateAccessToken(claims, 60L * 60 * 24 * 365 * 100); + member.setAccessToken(accessToken); + } return accessToken; } + + // 해당 토큰이 화이트 리스트에 있는지 검증 + public boolean verifyWithWhiteList(Member member, String token) { + return member.getAccessToken().equals(token); + } } diff --git a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/filter/JwtAuthorizationFilter.java b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/filter/JwtAuthorizationFilter.java index 8c8bf12..314fd21 100644 --- a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/filter/JwtAuthorizationFilter.java +++ b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/filter/JwtAuthorizationFilter.java @@ -35,16 +35,19 @@ public class JwtAuthorizationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String barerToken = request.getHeader("Authorization"); - // 토큰 유효성 검증 + // 1. 1차 체크(정보가 변조되지 않았는지 검증) if(barerToken != null) { - String token = barerToken.substring("Barer ".length()); + // accessToken에서 회원 정보 가져오려면 Authentication에서 Bearer 제거 필요 + String token = barerToken.substring("Bearer ".length()); // 토큰이 유효하면 회원 정보 얻어서 강제 로그인 처리 if(jwtProvider.verify(token)) { Map claims = jwtProvider.getClaims(token); String username = (String) claims.get("username"); Member member = memberService.findByUsername(username); - if(member != null) { + // 2. 2차 체크(해당 엑세스 토큰이 화이트 리스트에 포함되는지 검증) + if (memberService.verifyWithWhiteList(member, token)) { + // 강제 로그인 처리 forceAuthentication(member); } } diff --git a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/jwt/JwtProvider.java b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/jwt/JwtProvider.java index c43c710..e5d9b2f 100644 --- a/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/jwt/JwtProvider.java +++ b/4Week_Mission/mutbooks/src/main/java/com/example/mutbooks/app/security/jwt/JwtProvider.java @@ -25,7 +25,7 @@ private SecretKey getSecretKey() { } // JWT Access Token 발급 - public String generateAccessToken(Map claims, int seconds) { + public String generateAccessToken(Map claims, long seconds) { long now = new Date().getTime(); Date accessTokenExpiresIn = new Date(now + 1000L * seconds);