JWT鉴权机制
1.JWT用于登录身份验证
2.用户登录成功后,后端通过JWT机制生成一个token,返回给客户端
3.客户端后续的每次请求都需要携带token,放在header的authorization中
4.后端从authorization中拿到token后,通过secretKey进行解密验证省份
JWT生成的Token由三部分组成:header.payload.signature
**header:**主要是声明采用的加密算法
alg:指定生成signature采用的加密算法,默认是HS256
typ:令牌类型,jwt
**payload:**载荷,消息体,这里存放实际的内容
exp:设置过期时间
uid:用户uid
除了设置过期时间和用户的uid,还可以添加自定义私有字段,使用base64url进行编码组成JWT的第二部分
signature:
js
Signature = HMACSHA256(base64Url(header)+.+base64Url(payload),secretKey)
优点:
- json具有通用性,所以可以跨语言
- 组成简单,字节占用小,便于传输
- 服务端无需保存会话信息,很容易进行水平扩展
- 一处生成,多处使用,可以在分布式系统中,解决单点登录问题
- 可防护CSRF攻击
缺点:
- payload部分仅仅是进行简单编码,所以只能用于存储逻辑必需的非敏感信息
- 需要保护好加密密钥,一旦泄露后果不堪设想
- 为避免token被劫持,最好使用https协议
共享登录SSO
同域名下的单点登录
cookie
的domain
属性设置为当前域的父域,并且父域的cookie
会被子域所共享。path
属性默认为web
应用的上下文路径
利用 Cookie
的这个特点,没错,我们只需要将Cookie
的domain
属性设置为父域的域名(主域名),同时将 Cookie
的path
属性设置为根路径,将 Session ID
(或 Token
)保存到父域中。这样所有的子域应用就都可以访问到这个Cookie
不过这要求应用系统的域名需建立在一个共同的主域名之下,如 tieba.baidu.com
和 map.baidu.com
,它们都建立在 baidu.com
这个主域名之下,那么它们就可以通过这种方式来实现单点登录
不同域名下的单点登录使用PostMessage
单点登录完全用前端来实现,前端拿到Token之后,前端通过 iframe
+postMessage()
方式,将同一份 Token
写入到了多个域下的 LocalStorage
中,前端每次在向后端发送请求之前,都会主动从 LocalStorage
中读取Token
并在请求中携带,这样就实现了同一份Token
被多个域所共享;此种实现方式完全由前端控制,几乎不需要后端参与,同样支持跨域
js
// 获取 token
var token = result.data.token;
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
var iframe = document.createElement("iframe");
iframe.src = "http://app1.com/localstorage.html";
document.body.append(iframe);
// 使用postMessage()方法将token传递给iframe
setTimeout(function () {
iframe.contentWindow.postMessage(token, "http://app1.com");
}, 4000);
setTimeout(function () {
iframe.remove();
}, 6000);
// 在这个iframe所加载的HTML中绑定一个事件监听器,当事件被触发时,把接收到的token数据写入localStorage
window.addEventListener('message', function (event) {
localStorage.setItem('token', event.data)
}, false);
认证中心来实现单点登录
当用户首次访问时,需要在认证中心登录:
1.当用户访问网站a.com下面的pageA页面,
2.由于没有登录,则系统A会返回给浏览器302重定向,并带上回调地址 www.sso.com?return_uri=a.com/pageA
,以便登录后直接进入对应页面。
3.重定向302之后,浏览器去访问重定向地址,认证中心验证未登录,则展示form,提示用户登录
4.用户在认证中心输入账号密码,提交登录
5.认证中心验证账号密码有效,然后重定向 a.com?ticket=123
带上授权码 ticket
,并将认证中心 sso.com
的登录态写入 Cookie
6.在 a.com
服务器中,拿着 ticket
向认证中心确认,授权码 ticket
真实有效。
7.验证成功后,服务器将登录信息写入 Cookie
(此时客户端有 2 个 Cookie
分别存有 a.com
和 sso.com
的登录态)