添加注销接口
This commit is contained in:
@@ -35,4 +35,10 @@ public class LoginController {
|
|||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
return loginService.smsLogin(dto.getMobileNumber(), dto.getCode(), dto.getInviteCode(), request, 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.JWT;
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jiayunet.constant.PreRedisKeyName;
|
import org.jiayunet.constant.PreRedisKeyName;
|
||||||
import org.jiayunet.constant.SmsTemplateEnum;
|
import org.jiayunet.constant.SmsTemplateEnum;
|
||||||
@@ -20,15 +21,13 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -163,4 +162,63 @@ public class LoginService {
|
|||||||
|
|
||||||
return new LoginVo(user.getId(), user.getNick());
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user