Spring Spring Security+JWTログイン-4の実装(リフレッシュトークンの実装)
31257 ワード
ymlファイルの変更
まずymlファイルでrefreshタグの有効期限を設定します.app:
jwtSecret: jwtsigntutorialasdfasdfasdfasdfasdf
jwtExpirationInMs: 604800000
# 여기 리프레시 한줄 추가
jwtRefreshExpirationInMs: 86400000
ペイロード(DTOの作成)
Request
TokenRefreshRequest.JAvaファイルpublic class TokenRefreshRequest {
@NotBlank
private String refreshToken;
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}
Response
既存のJwtAuthenticationResponse.java
ファイルでは、
refreshToken変数が追加されました.
app:
jwtSecret: jwtsigntutorialasdfasdfasdfasdfasdf
jwtExpirationInMs: 604800000
# 여기 리프레시 한줄 추가
jwtRefreshExpirationInMs: 86400000
Request
TokenRefreshRequest.JAvaファイル
public class TokenRefreshRequest {
@NotBlank
private String refreshToken;
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}
Response既存の
JwtAuthenticationResponse.java
ファイルでは、refreshToken変数が追加されました.
@Getter @Setter
public class JwtAuthenticationResponse {
private String accessToken;
private String refreshToken;
private String tokenType = "Bearer";
public JwtAuthenticationResponse(String accessToken, String refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
}
次にrefreshTokenを受信するクラスを作成します2. TokenRefreshResponse.java
@Getter @Setter
public class TokenRefreshResponse {
private String accessToken;
private String refreshToken;
private String tokenType = "Bearer";
public TokenRefreshResponse(String accessToken, String refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
}
コントローラの作成
既存のAuthController.java
ファイルにrefreshTokenロジックを追加します.@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
RefreshTokenService refreshTokenService;
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
JwtTokenProvider tokenProvider;
# 로그인 부분에 RefreshToken 추가
@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
#RefreshToken 로직 추가
RefreshToken refreshToken = refreshTokenService.createRefreshToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(jwt, refreshToken.getToken()));
}
# RefreshToken api 작성
@PostMapping("/refreshtoken")
public ResponseEntity<?> refreshtoken(@Valid @RequestBody TokenRefreshRequest tokenRefreshRequest) {
String requestRefreshToken = tokenRefreshRequest.getRefreshToken();
return refreshTokenService.findByToken(requestRefreshToken)
.map(refreshTokenService::verifyExpiration)
.map(RefreshToken::getUser)
.map(user -> {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
user.getEmail(), user.getPassword()
)
);
String token = tokenProvider.generateToken(authentication);
return ResponseEntity.ok(new TokenRefreshResponse(token, requestRefreshToken));
})
.orElseThrow(() -> new TokenRefreshException(requestRefreshToken, "Refresh token is not in database!"));
}
}
下から
Refresh Tokenモデルを作成します.
JWTRefresh Token Serviceが作成されます.
Create Refresh Token Service
モデルの作成
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
RefreshTokenService refreshTokenService;
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
JwtTokenProvider tokenProvider;
# 로그인 부분에 RefreshToken 추가
@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication);
#RefreshToken 로직 추가
RefreshToken refreshToken = refreshTokenService.createRefreshToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(jwt, refreshToken.getToken()));
}
# RefreshToken api 작성
@PostMapping("/refreshtoken")
public ResponseEntity<?> refreshtoken(@Valid @RequestBody TokenRefreshRequest tokenRefreshRequest) {
String requestRefreshToken = tokenRefreshRequest.getRefreshToken();
return refreshTokenService.findByToken(requestRefreshToken)
.map(refreshTokenService::verifyExpiration)
.map(RefreshToken::getUser)
.map(user -> {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
user.getEmail(), user.getPassword()
)
);
String token = tokenProvider.generateToken(authentication);
return ResponseEntity.ok(new TokenRefreshResponse(token, requestRefreshToken));
})
.orElseThrow(() -> new TokenRefreshException(requestRefreshToken, "Refresh token is not in database!"));
}
}
モデルの作成
RefreshToken.java
@Getter @Setter
@Entity(name = "refreshtoken")
public class RefreshToken {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne
@JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
@Column(nullable = false, unique = true)
private String token;
@Column(nullable = false)
private Instant expiryDate;
}
リポジトリの作成
RefreshTokenRepository.java
public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
@Override
Optional<RefreshToken> findById(Long id);
Optional<RefreshToken> findByToken(String token);
int deleteByUser(User user);
}
サービスの作成
RefreshTokenService.java
@Service
public class RefreshTokenService {
@Value("${app.jwtRefreshExpirationInMs}")
private Long refreshTokenDurationMs;
@Autowired
private RefreshTokenRepository refreshTokenRepository;
@Autowired
private UserRepository userRepository;
public Optional<RefreshToken> findByToken(String token) {
return refreshTokenRepository.findByToken(token);
}
public RefreshToken createRefreshToken(Authentication authentication) {
UserPrincipal userPrincipal = (UserPrincipal)authentication.getPrincipal();
RefreshToken refreshToken = new RefreshToken();
refreshToken.setUser(userRepository.findById(userPrincipal.getId()).get());
refreshToken.setExpiryDate(Instant.now().plusMillis(refreshTokenDurationMs));
refreshToken.setToken(UUID.randomUUID().toString());
refreshToken = refreshTokenRepository.save(refreshToken);
return refreshToken;
}
public RefreshToken verifyExpiration(RefreshToken token) {
if (token.getExpiryDate().compareTo(Instant.now()) < 0) {
refreshTokenRepository.delete(token);
throw new TokenRefreshException(token.getToken(), "Refresh token was expired. Please make a new signin request");
}
return token;
}
@Transactional
public int deleteByUserId(Long userId) {
return refreshTokenRepository.deleteByUser(userRepository.findById(userId).get());
}
}
例外処理Exceptionの作成
TokenRefreshException.java@ResponseStatus(HttpStatus.FORBIDDEN)
@Getter
@Setter
public class TokenRefreshException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TokenRefreshException(String token, String message) {
super(String.format("Failed for [%s]: %s", token, message));
}
}
Reference
この問題について(Spring Spring Security+JWTログイン-4の実装(リフレッシュトークンの実装)), 我々は、より多くの情報をここで見つけました
https://velog.io/@modsiw/Spring-Spring-Security-JWT-로그인-구현-해보기-4-refresh-token-구현
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
@ResponseStatus(HttpStatus.FORBIDDEN)
@Getter
@Setter
public class TokenRefreshException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TokenRefreshException(String token, String message) {
super(String.format("Failed for [%s]: %s", token, message));
}
}
Reference
この問題について(Spring Spring Security+JWTログイン-4の実装(リフレッシュトークンの実装)), 我々は、より多くの情報をここで見つけました https://velog.io/@modsiw/Spring-Spring-Security-JWT-로그인-구현-해보기-4-refresh-token-구현テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol