飞雪连天射白鹿,笑书神侠倚碧鸳

0%

网站前端登录原理

登录/扫码,背后用到了什么功能

最近也是看到一个需求,网站接入微信扫码登录,并且扫码同时还需要关注公众号,那么就乘此时机回顾下各类登录方式


经典的登录模式

由于http的无状态特性,服务端是不知道客户端是谁的,也就无法判断每次请求的用户是否相关联,所以不知道用户是否已经是登录态

cookie作用是服务端发送给客户端的字符串,以文本方式保存,再下次请求时携带

session是服务端对接收的信息进行验证,服务端会分配一个内存区域/文件/数据库,用于缓存session对象

流程

  • 首次登录
    • 用户访问页面,输入密码
    • 验证成功,分配sessionId
    • 响应头写入cookie,告知客户端登录成功
  • 二次登录
    • 用户发送请求携带cookie给服务端
    • 验证有效,允许访问,表示cookie中解析出来的sessionId一致
    • 验证失效,重新登录

问题

  • 客户端数量上升,服务端需分配更大量的空间存放sessionId,增大服务端压力
  • 分布式/集群,同步登录态需要每一台机器
  • sessionId存放在cookie中,有CSRF攻击风险
    • 这里简述跨站脚本攻击,中间人无法拿到/解析cookie,但是能通过真实cookie向服务端发送请求,改变发送的数据,所以攻击的是改POST,而非读GET
    • 如果业务走安全审计流程么,一般会给出具体的解决方案(专业审计,价格老贵了,四大审计真的业务方向啥都审)
      • 验证 HTTP Referer 字段
      • 在请求地址中添加 token 并验证
      • 在 HTTP 头中自定义属性并验证

token

token优化了传统cookie+session的服务端压力问题,之前我最常用的则是JWT

流程

  • 首次登录
    • 用户访问页面,输入密码
    • 验证成功,生成token
    • 返回token,告知客户端登录成功
  • 二次登录
    • 用户发送请求携带token给服务端
    • 验证有效,允许访问
    • 验证失效,重新登录

特点

  • 服务端无需保存,利用客户端天然的分布式优势缓存token,每次请求时校验
  • 不存在cookie中
  • 登录态有效期由服务端决定

JWT

格式为header.playload.signature字符串

头部指定签名算法,消息体包含数据,签名对前两部base64url+对称加密

当然不一定要强制按格式,能够产生类似功能的字符串与服务端匹配就可以称为JWT

服务端拿到字符串后执行相同对称加密动作,判断签名一致

  • 问题点在于对称加密,密钥是暴露的
  • 但是前端安全的本质是防止中间人通过各种方式篡改/攻击数据库,执行改权限之前是经过其他权限验证的真实用户,不能防止黑客作为真实用户去进行请求
  • 所以JWT也是有价值的,当然更大的价值在于减轻服务端压力

SSO单点登录

品牌内部的公共认证中心,所有产品一次登录,其他产品无需登录,常见比如腾讯的子域名游戏、综艺等

流程

  • 首次登录
    • 用户访问页面A,跳转到renz认证中心统一登录页B,并url带上redirect地址,发送请求并验证
    • 输入密码,认证中心验证成功,创建全局会话&ticket
    • 带上统一登录的登录态cookie,重定向跳转回页面A,此时url上含有ticket
    • 页面A请求,认证中心验证ticket有效,带上页面A的登录态cookie
    • 登录成功,客户端有2个cookie
  • 二次登录页面A
    • 验证ticket,cookie已存在,令牌有效,登录成功
  • 二次登录页面B
    • 通过认证中心统一登录页B,验证认证中心登录态
    • 验证通过,带上ticket重定向回B
  • 退出
    • 在验证ticket时,请求为退出的api接口即可
    • 清除c的登录态cookie
    • 清除认证中心的cookie,执行退出方法
    • 遍历下发过ticket的产品,执行的退出方法

Oauth

比如微信、qq、微博,授权机制,客户端携带令牌可以访问所有者的资源

  • 接入的第三方应用获取appid,appsecret
  • 用户进入时,跳转平台Oauth授权,平台发送请求用户确认
  • 确认后重新进入第三方站点,并带上临时code
  • 第三方应用根据code、id、secret向平台申请token
  • 第三方应用拿到用户信息,保存登录态

Oauth2.0

获取token的过程,4种授权方式,都需要第三方有appid和appsecret,需要分发token和refresh

  • 授权码,最复杂,安全高,如微信
  • 隐藏式,客户端直接获取token
  • 密码式,第三方拿用户账密登录平台,危险风险大
  • 凭证式,客户端分配了id,secret标识身份

token放header中

令牌过期处理

token是有时效的,重新授权的流程体验不好,更优雅得处理过期问题

一个令牌请求API,一个令牌请求refresh_token,当一个失效时,下一次请求更新token,即可优化前端流程

扫码登录及关注

简述一下思路,扫码后&关注默认为已授权

  • 嵌入网页的平台二维码展示,客户端存jwt用于验证
  • 服务端生成微信临时带参二维码,每三分钟更新
  • 客户端每隔3秒请求一次API获取最新状态,5次后每隔5秒,再往后时间间隔变长,优化请求,这里也可以用socket更简洁(简述三点接口性能,有空写一篇关于socket的)
    • 大量链接的创建和关闭
    • 长时间保持大量连接
    • 大量推送消息
  • 用户扫码后关注/直接进入公众号,服务端根据临时二维码区分渠道,得到授权状态,更新API、token、数据库
  • 客户端切换页面内容A,刷新页面从缓存中取token值,验证成功后直接进入页面A,不再重新扫码
  • 授权/关注流程结束,需求实现
听说,打赏我的人最后都找到了真爱
↘ 此处应有打赏 ↙
// 用户脚本