weblog/doc/7、Gateway 网关搭建与接口鉴权/7.8 用户退出登录接口开发.md
2025-02-17 11:57:55 +08:00

5.9 KiB
Raw Blame History

上小节 中,我们已经实现了网关透传用户 ID 给下游服务,下游服务知道了请求对应的用户 ID才能方便的处理相关业务比如用户退出登录。本小节中就来把用户退出登录接口开发完成。

接口定义

接口地址

POST /user/logout

入参

无入参。只需请求头中携带上 Token 即可。

出参

{
	"success": true, // true 表示退出登录成功
	"message": null,
	"errorCode": null,
	"data": null
}

编写业务逻辑

之前测试权限校验的时候,退出登录接口已经在认证服务中定义好了,接下来,仅需补充对应逻辑即可。

service 业务层

编辑 UserService 业务接口,声明一个退出登录方法,入参为请求头透传过来的用户 ID, 代码如下:

package com.quanxiaoha.xiaohashu.auth.service;

import com.quanxiaoha.framework.common.response.Response;
import com.quanxiaoha.xiaohashu.auth.model.vo.user.UserLoginReqVO;

public interface UserService {

	// 省略...

    /**
     * 退出登录
     * @return
     */
    Response<?> logout(Long userId);

}

接着,编辑其实现类 UserServiceImpl,实现上述方法,并添加逻辑代码如下:

package com.quanxiaoha.xiaohashu.auth.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.quanxiaoha.framework.common.enums.DeletedEnum;
import com.quanxiaoha.framework.common.enums.StatusEnum;
import com.quanxiaoha.framework.common.exception.BizException;
import com.quanxiaoha.framework.common.response.Response;
import com.quanxiaoha.framework.common.util.JsonUtils;
import com.quanxiaoha.xiaohashu.auth.constant.RedisKeyConstants;
import com.quanxiaoha.xiaohashu.auth.constant.RoleConstants;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.PermissionDO;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.RoleDO;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.UserDO;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.UserRoleDO;
import com.quanxiaoha.xiaohashu.auth.domain.mapper.RoleDOMapper;
import com.quanxiaoha.xiaohashu.auth.domain.mapper.UserDOMapper;
import com.quanxiaoha.xiaohashu.auth.domain.mapper.UserRoleDOMapper;
import com.quanxiaoha.xiaohashu.auth.enums.LoginTypeEnum;
import com.quanxiaoha.xiaohashu.auth.enums.ResponseCodeEnum;
import com.quanxiaoha.xiaohashu.auth.model.vo.user.UserLoginReqVO;
import com.quanxiaoha.xiaohashu.auth.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

   // 省略...

    /**
     * 退出登录
     *
     * @param userId
     * @return
     */
    @Override
    public Response<?> logout(Long userId) {
        // 退出登录 (指定用户 ID)
        StpUtil.logout(userId);
        
        return Response.success();
    }

    // 省略...

}

逻辑很简单,通过 SaToken 的工具类方法 StpUtil.logout(userId); ,传入想要退出登录的用户 ID 即可。

Controller 层

最后,编辑 UserController 控制器,修改代码如下:

package com.quanxiaoha.xiaohashu.auth.controller;

import com.quanxiaoha.framework.biz.operationlog.aspect.ApiOperationLog;
import com.quanxiaoha.framework.common.response.Response;
import com.quanxiaoha.xiaohashu.auth.model.vo.user.UserLoginReqVO;
import com.quanxiaoha.xiaohashu.auth.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @author: 犬小哈
 * @date: 2024/5/29 15:32
 * @version: v1.0.0
 * @description: TODO
 **/
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Resource
    private UserService userService;

    // 省略...

    @PostMapping("/logout")
    @ApiOperationLog(description = "账号登出")
    public Response<?> logout(@RequestHeader("userId") String userId) {
        return userService.logout(Long.valueOf(userId));
    }

}

测试一波

代码编写完毕后,重启一下认证服务。在测试登出接口之前,观察 Redis 中存储的会话信息,先确认一下等会要退出登录的 Token 是否存在,存在则说明对应的用户处于登录状态,如下图所示:

打开 Apipost 工具, 测试一波退出登录接口,如下所示:

响参提示操作成功,再来观察一下 Redis 中该 Token 是否还在,如下图所示,可以看到之前存在的 Token ,已经被删除了,会话信息也被删除了:

为了再次验证一下,用刚才的 Token 令牌,再次调用退出登录接口,响参也提示当前 Token 已经无效了:

至此,用户退出登录接口就开发完成啦,是不是很简单~

本小节源码下载

https://t.zsxq.com/GudWD