添加注销接口

This commit is contained in:
zk
2026-03-21 10:54:44 +08:00
parent 0039e0aca0
commit 004464471d
2 changed files with 68 additions and 4 deletions
@@ -35,4 +35,10 @@ public class LoginController {
HttpServletResponse response) {
return loginService.smsLogin(dto.getMobileNumber(), dto.getCode(), dto.getInviteCode(), request, response);
}
@PostMapping("/logout")
public boolean logout(HttpServletRequest request, HttpServletResponse response) {
loginService.logout(request, response);
return true;
}
}
@@ -2,6 +2,7 @@ package org.jiayunet.service;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.jiayunet.constant.PreRedisKeyName;
import org.jiayunet.constant.SmsTemplateEnum;
@@ -20,15 +21,13 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -163,4 +162,63 @@ public class LoginService {
return new LoginVo(user.getId(), user.getNick());
}
/**
* 退出登录
* <p>1. 获取当前用户ID和设备uuId 2. 如果uuId为空则删除整个Redis key,否则从Redis中移除当前设备 3. 清除Cookie</p>
*/
public void logout(HttpServletRequest request, HttpServletResponse response) {
// 获取当前token
Cookie[] cookies = request.getCookies() == null ? new Cookie[0] : request.getCookies();
String token = Arrays.stream(cookies).filter(c -> "Token".equals(c.getName())).map(Cookie::getValue).findFirst().orElse(null);
token = token == null ? request.getHeader("Token"): token;
Assert.hasText(token,"无效登录状态");
// 解析 获取用户和设备id
Algorithm algorithm = Algorithm.HMAC256(secret);
DecodedJWT verify = JWT.require(algorithm).build().verify(token);
String uuid = verify.getClaim("uuId").asString();
String userId = verify.getClaim("userId").asString();
// 查询缓存key
String redisKey = PreRedisKeyName.LOGIN_TOKEN + userId;
RedisLoginTokenInfo info = redisServerTool.get(redisKey, RedisLoginTokenInfo.class);
if (info == null) { delCookie(response);return;}
// 剔除登录id
List<RedisLoginTokenInfo.LoginDevice> loginDevices = CollectionUtils.isEmpty(info.getLoginDevices()) ? List.of() : info.getLoginDevices();
loginDevices = loginDevices.stream().filter(v-> !Objects.equals(v.getUuId(), uuid)).toList();
// 修改redis记录
if (CollectionUtils.isEmpty(loginDevices)) {
// 无设备 直接删除key
redisServerTool.delete(redisKey);
delCookie(response);
return;
}
info.setLoginDevices(loginDevices);
redisServerTool.set(redisKey, info, tokenExceedTime, TimeUnit.SECONDS);
delCookie(response);
}
/**
* 删除cookie
*/
private void delCookie(HttpServletResponse response) {
// 清除Cookie
Cookie cookie = new Cookie("Token", null);
cookie.setHttpOnly(true);
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}