我正在使用JWT在我的Spring Boot应用程序中进行身份验证.以下是身份验证服务中的方法:
public AuthenticationResponse authenticate(AuthenticationRequest request) {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getEmail(),
request.getPassword()
)
);
User user = userRepository.findByEmail(request.getEmail()).orElseThrow(UserNotFoundException::new);
String jwtToken = jwtService.generateToken(user);
String refreshToken = jwtService.generateRefreshToken(user);
revokeAllUserTokens(user);
saveUserToken(user, jwtToken);
return AuthenticationResponse.builder()
.accessToken(jwtToken)
.refreshToken(refreshToken)
.build();
}
private void revokeAllUserTokens(User user) {
List<Token> validUserTokens = tokenRepository.findAllValidTokenByUser(user.getId());
if(validUserTokens.isEmpty())
return;
validUserTokens.forEach(token -> {
token.setExpired(true);
token.setRevoked(true);
});
tokenRepository.saveAll(validUserTokens);
}
private void saveUserToken(User user, String jwtToken) {
Token token = Token.builder()
.user(user)
.token(jwtToken)
.tokenType(TokenType.BEARER)
.expired(false)
.revoked(false)
.build();
tokenRepository.save(token);
}
在JwtService中:
public String generateToken(UserDetails userDetails) {
return generateToken(new HashMap<>(), userDetails);
}
public String generateToken(Map<String, Object> extraClaims, UserDetails userDetails) {
return buildToken(extraClaims, userDetails, jwtConfig.getExpiration());
}
public String generateRefreshToken(UserDetails userDetails) {
return buildToken(new HashMap<>(), userDetails, jwtConfig.getRefreshTokenExpiration());
}
和令牌在数据库中:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "jwt_tokens")
public class Token {
@Id
@GeneratedValue
public Long id;
@Column(name = "token", unique = true)
public String token;
@Enumerated(EnumType.STRING)
public TokenType tokenType = TokenType.BEARER;
public boolean revoked;
public boolean expired;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
public User user;
}
实现的其余部分是不言而喻的.
它工作得很好,但当有多个身份验证请求时(当我快速发送多个请求时),会有500个状态响应,并抛出一个异常(AuthenticationService中的方法Authate)被调用:
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.CONSTRAINT_INDEX_4 ON PUBLIC.JWT_TOKENS(TOKEN NULLS FIRST) VALUES ( /* 7 */ 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJtYWx5enNAZW1haWwuY29tIiwiaWF0IjoxNjkwMjE4NDU3LCJleHAiOjE2OTAzMDQ4NTd9.8aePz6jl3JPvsnDFVpXxtzYfsxLN0ZqIUg0FsK_XDaE' )"; SQL statement:
insert into jwt_tokens (expired,revoked,token,token_type,user_id,id) values (?,?,?,?,?,?) [23505-214]