java redis token实时更新权限
时间: 2023-07-06 12:33:32 浏览: 122
在Java中使用Redis实时更新Token的权限可以通过以下步骤实现:
1. 创建一个Token工具类,用于生成Token和验证Token的有效性。
```java
@Component
public class TokenUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
/**
* 生成Token
* @param userDetails 用户信息
* @return Token字符串
*/
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("sub", userDetails.getUsername());
claims.put("created", new Date());
return Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 验证Token是否有效
* @param token Token字符串
* @param userDetails 用户信息
* @return 验证结果
*/
public boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
/**
* 从Token中获取用户名
* @param token Token字符串
* @return 用户名字符串
*/
public String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
/**
* 生成Token过期时间
* @return 过期时间Date对象
*/
private Date generateExpirationDate() {
return new Date(System.currentTimeMillis() + expiration * 1000);
}
/**
* 判断Token是否过期
* @param token Token字符串
* @return 判断结果
*/
private boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
/**
* 从Token中获取过期时间
* @param token Token字符串
* @return 过期时间Date对象
*/
private Date getExpirationDateFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getExpiration();
}
}
```
2. 创建一个Token存储工具类,用于将Token存储到Redis中,以及从Redis中获取和删除Token。
```java
@Component
public class RedisTokenStore {
private static final String REDIS_TOKEN_PREFIX = "token:";
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 将Token存储到Redis中
* @param token Token字符串
* @param userDetails 用户信息
*/
public void storeToken(String token, UserDetails userDetails) {
redisTemplate.opsForValue().set(getRedisKey(userDetails.getUsername()), token, TokenUtils.EXPIRATION);
}
/**
* 从Redis中获取Token
* @param userDetails 用户信息
* @return Token字符串
*/
public String getToken(UserDetails userDetails) {
return redisTemplate.opsForValue().get(getRedisKey(userDetails.getUsername()));
}
/**
* 从Redis中删除Token
* @param userDetails 用户信息
*/
public void deleteToken(UserDetails userDetails) {
redisTemplate.delete(getRedisKey(userDetails.getUsername()));
}
/**
* 获取Redis中Token的Key
* @param username 用户名
* @return Redis Key字符串
*/
private String getRedisKey(String username) {
return REDIS_TOKEN_PREFIX + username;
}
}
```
3. 在登录成功后,使用TokenUtils生成Token,并将Token存储到Redis中。
```java
@Autowired
private TokenUtils tokenUtils;
@Autowired
private RedisTokenStore redisTokenStore;
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<?> login(@RequestBody LoginDto loginDto) {
// 验证用户名和密码
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginDto.getUsername(),
loginDto.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成Token并将Token存储到Redis中
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String token = tokenUtils.generateToken(userDetails);
redisTokenStore.storeToken(token, userDetails);
// 返回Token
return ResponseEntity.ok(new AuthTokenDto(token));
}
```
4. 在每次请求时,使用拦截器或过滤器从请求中获取Token,并验证Token的有效性。如果Token无效,则返回401 Unauthorized响应。
```java
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private TokenUtils tokenUtils;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private RedisTokenStore redisTokenStore;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authToken = request.getHeader("Authorization");
if (authToken != null && authToken.startsWith("Bearer ")) {
authToken = authToken.substring(7);
String username = tokenUtils.getUsernameFromToken(authToken);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (tokenUtils.validateToken(authToken, userDetails)) {
String redisToken = redisTokenStore.getToken(userDetails);
if (redisToken == null || !redisToken.equals(authToken)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token has been revoked");
return;
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
```
5. 在用户更新权限时,从RedisTokenStore中删除该用户的Token,使得该用户需要重新登录来获取新的Token。
```java
@Autowired
private RedisTokenStore redisTokenStore;
public void revokeUserToken(String username) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
redisTokenStore.deleteToken(userDetails);
}
```
通过以上步骤,您可以使用Redis实时更新Token的权限,从而保证用户的权限更新能够及时生效。
阅读全文