优化实战 第 25 期 您所在的位置:网站首页 前端json数据给后端数据 优化实战 第 25 期

优化实战 第 25 期

2023-03-21 08:52| 来源: 网络整理| 查看: 265

SSO.jpg

单点登录 (Single Sign On),简称为 SSO,是指在同一账号平台下的多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统

举个例子,系统A 和 系统B 都属于某公司下的两个不同的应用系统,当用户登录 系统A 后,再打开 系统B ,系统便会自动帮用户登录 系统B ,这种现象就属于单点登录

JWT鉴权原理

cc420cac591448b1b6a279efa5c5d52e.png

1、客户端使用账号和密码请求登录

2、服务端收到请求,去验证账号与密码

3、验证通过后,服务端会签发一个令牌 Token 并把这个令牌发送给客户端

4、客户端收到令牌将其存储到本地 localStorage 中

5、客户端每次向服务端请求资源时都需要在 Header Authorization 中携带令牌,允许用户访问该令牌允许的路由、服务和资源

6、服务端收到请求后进行解密并通过秘钥验证令牌,验证通过返回资源,不通过则返回 401 状态码

JWT的介绍

fc1f4134970a304ea501a2f40d06848fc8175cf0.png

JSON Web Token ,简称 JWT ,一种基于 JSON 的认证授权机制,是一个非常轻巧的标准规范。这个规范允许我们在用户和服务器之间传递安全可靠的信息

JWT 也是目前最流行的跨域认证解决方案

JWT的构成

头部(Header)

{ "alg": "HS256", "typ": "jwt" } 复制代码

通常由令牌的类型 typ 和所使用的签名算法 alg 组成,并使用 Base64URL 进行编码组成 JWT 结构的第一部分

载荷(Payload)

{ "exp": Math.floor(Date.now() / 1000 + 60 * 60), // 设置有效期为 1 个小时 "uid": "188888" } 复制代码

除了设置过期时间 exp 和用户的 uid ,还可以添加自定义私有字段,使用 Base64URL 进行编码组成 JWT 结构的第二部分

签名(Signature)

71cf3bc79f3df8dcf8062d8f12df5182461028c8.png

HMACSHA256(base64UrlEncode(Header) + "." + base64UrlEncode(payload), secret) 复制代码

在服务端设置一个私钥 secret ,使用 Header 指定的算法 HS256 对头部 Header 和 载荷 Payload 进行加密生成签名。

生成 Token

把 Header、Payload、Signature 拼成一个用 英文句号 分隔的字符串,即为 Token

jwt_token.webp

进行验签

服务端利用签名可以校验 Token 是否被篡改

2934349b033b5bb55554ae46ea1df630b400bcdb.png

注意事项

默认 JWT 是不加密的,所以不要把重要信息放在载荷 Payload 部分

保存在服务端的 secret 是用来进行 JWT 的签发和验证的,所以在任何场景都不应该泄漏出去。如果客户端得知了这个 secret ,那就意味着客户端可以对 JWT 进行自我签发

JWT的特点

无状态化

由于服务器或 Session 中不会存储任何用户信息,所以基于 Token 的用户认证是一种服务器无状态的认证方式

没有会话信息意味着应用程序可以根据需要扩展和添加更多的机器(服务器集群),而不需要考虑用户是在哪一台服务器登录的,适用于 分布式系统

易于扩展

由于 JWT 存储在应用系统,服务端不进行会话存储,所以便于服务端集群水平扩展

可以在 JWT 中的载荷 Payload 部分添加自定义的内容用于业务需要

支持跨域

由于 Token 存储于应用系统,完全由应用系统管理,既减轻了服务端的内存压力也避开了 同源策略 的限制

这样就可以给任何域名提供 API 服务,不需要担心跨域资源共享问题,即 CORS

防止 CSRF 攻击

前端向服务端发送请求时,将本地存储的 Token 手动添加到 Authorization 的请求头字段中,这样就避免了 CSRF 漏洞攻击

共享登录状态

实现方案

前端拿到 Token 后,不仅要将它写入当前域下的 localStorage 中,还要通过 iframe + postMessage() 的方式将它写入多个信任的其他域下的 localStorage 中,从而实现登录状态的共享

iframe_postMessage.jpeg

实现代码

将 Token 写入多个域名下的 localStorage 中

const iframe = document.createElement('iframe') iframe.src = 'http://www.app.com/static/bridge.html' iframe.addEventListener('load', event => { iframe.contentWindow.postMessage(token, 'http://www.app.com/static/bridge.html') }) document.body.append(iframe) 复制代码

在 iframe 加载的页面中绑定事件监听器,用来接收 Token 数据

window.addEventListener('message', ({ data, origin, srouce }) => { localStorage.setItem('AUTH-TOKEN', data) }) 复制代码

在各个应用系统请求的 Header 中携带 Token 令牌

config.headers.common['Authorization'] = 'Bearer ' + token 复制代码

说明:Bearer 是 JWT 的认证头部信息

总结

这种实现方式完全由前端控制,几乎不需要后端参与且支持跨域;出于安全因素考虑应始终使用 origin 和 source 属性验证发信息人的身份

Token 的安全性

安全概览

为了减少 JWT Token 的泄漏风险,其有效期应该设置得短一些并采用 HTTPS 协议。这样就会存在 JWT Token 过期的情况,导致用户频繁的去登录获取新的 JWT Token,严重影响用户体验

解决方案

生成 JWT Token 的同时生成 refresh_token,其中 refresh_token 的有效时间长于 JWT Token,当 JWT Token 过期之后,使用 refresh_token 获取新的 JWT Token 与 refresh_token,这样用户就可以享受无感知的刷新体验

每个 Refresh Token 只能使用一次

一起学习,加群交流看 沸点



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有