单点登陆设计

来源:互联网 发布:环境检测数据弄虚作假 编辑:程序博客网 时间:2024/05/22 01:33

  • 一登陆流程怎么设计和编码
      • 1名词扫盲
      • 2登陆设计
      • 3 token安全性

一、登陆流程怎么设计和编码

1.1名词扫盲

  • 认证中心:一个独立的服务,用于统一认证和统一权限
  • 客户端:任何一个子系统
  • 过滤器:客户端common类,任何客户端都需要依赖,所有有关权限的操作都要经过过滤器进行委托认证
  • 全局会话:认证中心和浏览器的会话
  • 局部会话:客户端自己的会话(客户端和浏览器的会话)

局部会话存在,全局会话一定存在
全局会话存在,局部会话不一定存在
全局会话销毁,局部会话必须销毁

1.2登陆设计

第一步:客户端发送账号密码到认证中心。(客户端无须编写登陆逻辑,只要post认证中心的loginUrl即可)
第二步:认证中心验证账号密码生成全局会话和token返回给客户端
第三步:客户端接收到token,经过过滤器将token发送到认证中心验证有效性
第四步:验证成功进行登陆,建立客户端局部会话
下面结合时序图和代码帮助理解

Created with Raphaël 2.1.0客户端客户端过滤器过滤器认证中心认证中心用户输入账号密码发送账号密码到认证中心验证账号密码返回token发送token验证token验证成功登陆成功

shiro filter代码片段,此方法相当于时序图中的filter角色

      /**token是否失效,token失效有两个场景       ** 一:子系统会话还存在的时候重复登陆,导致全局token不一致。       ** 二:认证中心强制下线       */      if(isLogin(request)) {//客户端已经登陆(局部会话已经存在)            if(!tokenAvailable()){//token失效                //当前token失效后,进行token验证,如果地址含有token,则重新进行验证和登陆                if(reLoginIfTokenEnable(request, response)){                    return true;                }                else{                    //已经登陆并且token无效,此处跳转到登陆界面                    return false;                }            }            return true;        }        //url没有携带token参数,则向认证中心申请token        if(noHasToken(request)){            return doAuthBySsoServer(request,response);        }        //已经获取到认证中心token,对token进行验证和登陆,建立局部会话        if(isAuth(request)){            return loginBySsoToken(request,response,request.getParameter("token"));        }        return true;    }

1.3 token安全性

假如token暴漏或者通过抓包取到token进行模拟登陆怎么办?通过设计上可以避免这种情况,首先token是一个对象,可以添加一个alreadyVerify布尔属性,判断该token是否已经被验证过了,已经验证过的token将不在进行第二次验证。原理很简单,只要某一个子系统登陆,那么alreadyVerify就为true,表明已经验证过。其他电脑抓取到token也是无法登陆的。那么假如同一个浏览器要登陆其他子系统呢?上面的设计限制了只能登陆一个子系统(因为alreadyVerify被设置为true)。其实在同一个浏览器,全局会话是存在的,只要判断全局会话存在,认证中心可以改变alreadyVerify属性令其为false,这样其他子系统就可以校验token成功了,下面是认证中心校验token的代码

java
public boolean verify(String token) {
Token tk = redis.get(token);
if(tk==null){//toklen不存在,token校验失效
return false;
}
if(tk.isAlreadyVerify())return false;//tk已经被使用过,失效
if(tk.getToken().equals(token)) {//验证通过
return true;
}
return false;
}

点击下面阅读

redis在线用户设计

0 0
原创粉丝点击