Cookies机制实现系统超时退出

171 阅读2分钟

image.png

背景

最近开发了两个工具性小项目(迁移工具、备份工具),本身在需求上没有登陆、退出、鉴权一系列功能。然而临近交付,客户又提出一点小小的安全要求,要有登录、退出,又要超时退出。这种在临交付之前的既要又要,只能做最简单的登录认证体系。

登录·退出

因为存在操作日志的缘故,只能以接口形式实现,服务端还需一点点介入。服务端接口只进行简单的账号/密码对比,Token管理放到客户端处理。

登录

输入超管账号/密码完成登录,登录成功后生成uuid作为Token设置进Cookie

  handleLogin = (err, values) => {
    const { dispatch, login } = this.props;
    dispatch({
      type: 'user/login',
      payload: { user: values?.account, passwd: values.password },
      callback() {
        // 构建唯一uuid作为Token
        setAccessToken(uuid());
        // 登录成功,直接跳转首页
        history.replace('/');
      },
      errorback() {
        notification.error({ message: '账号/密码错误' });
      },
    });
  };

设置Cookie

征求客户意见后,空闲后过期时间设置为1小时

  // 设置1小时过期的Cookie
  export function setAccessToken(str) {
      // 获取当前时间
      const now = new Date();

      // 计算60分钟后的时间
      const oneMinuteLater = new Date(now.getTime() + (60 * 60 * 1000)); 

      return Cookies.set('access_token', str, { expires: oneMinuteLater });
   }

退出

退出操作,清理Token并跳转到登录页

  dispatch({
    type: 'user/logout',
    callback() {
      removeAccessToken();
      history.replace('/user/login');
    },
    errorback() {
      notification.error({ message: '退出失败' });
    },
  });

Token超时退出

超时退出模拟服务端实现的机制,在用户有操作的情况下Token过期时间后延,只有在系统空闲场景下,1小时后退出。

区分系统繁忙·空闲

  • 繁忙:系统存在用户手动操作的接口访问
  • 空闲:系统不存在用户手动操作的接口访问

有简单的概念定义后,甄别所有类别接口,系统存在用户手动操作的接口访问定义为:

  • 非轮询访问的接口
  • 非退出接口

更新Token过期时间

系统在用户操作接口,并请求成功的场景下,顺延1小时过期时间。在Http拦截器中处理如下,Cookies中Token一旦过期,记录就会获取为空,跳转登录页。如果是定义的繁忙操作,执行更新Token超时操作。

const ignoreCheckTokenApi = ['/users/logout'];

return fetch(url, newOptions).then((response) => {
      const currentToken = getAccessToken();
      if (!currentToken) {
        history.replace('/user/login');
      }

      // 非轮询接口,排除退出接口,更新Cookie中Token超时间
      if(!newOptions?.headers?.isPolling && !ignoreCheckTokenApi.some((v) => newUrl.includes(v))) {
        setAccessToken(currentToken);
      }
      
 }

优化思路

可能会存在一个页面存在并发访问很多接口的场景,可以在合并更新方向优化,经过简单测试发现并没有对性能有什么影响,大写的OK。

后记

只适合简单、安全要求不高的项目,构建一种麻雀虽小肝胆俱全的安全要求。