ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于JWT 和Token(转)

2022-08-07 18:01:06  阅读:219  来源: 互联网

标签:Google JWT token 用户 access Token API 关于


转自关于JWT 和Token

关于 Token

token 即使是在计算机领域中也有不同的定义,这里我们说的token,是指访问资源的凭据。例如当你调用Google API,需要带上有效 token 来表明你请求的合法性。这个 token 是 Google 给你的,这代表 Google 给你的授权使得你有能力访问 API 背后的资源。
请求 API 时携带 token 的方式也有很多种,通过 HTTP Header 或者 url 参数 或者 google 提供的类库都可以:

// HTTP Header:
GET /drive/v2/files HTTP/1.1
Authorization: Bearer <token>
Host: www.googleapis.com/

// URL query string parameter
GET https://www.googleapis.com/drive/v2/files?token=<token>

// Python:
from googleapiclient.discovery import build
drive = build('drive', 'v2', credentials=credentials)

更具体的说,上面用于调用 API 的 token 我们称为细分为 access token。通常 access token 是有有效期限的,如果过期就需要重新获取。那么如何重新获取?现在我们要让时光倒流一会,回顾第一次获取 token 的流程是怎样的:

首先你需要向 Google API 注册你的应用程序,注册完毕之后你会拿到认证信息(credentials)包括
ID 和 secret。不是所有的程序类型都有 secret。
接下来就要向 Google 请求 access token。这里我们先忽略一些细节,例如请求参数(当然需要上面申请到的 secret)以及不同类型的程序的请求方式等。重要的是,如果你想访问的是用户资源,这里就会提醒用户进行授权。
如果用户授权完毕。Google 就会返回 access token。又或者是返回授权代码(authorization code),你再通过代码取得 access token
token 获取到之后,就能够带上 token 访问 API 了

OAuth

SSO (Single sign-on)

通常公司内部会有非常多的工具平台供大家使用,比如人力资源,代码管理,日志监控,预算申请等等。如果每一个平台都实现自己的用户体系的话无疑是巨大的浪费,所以公司内部会有一套公用的用户体系,用户只要登陆之后,就能够访问所有的系统。这就是单点登录(SSO: Single Sign-On)
SSO 是一类解决方案的统称,而在具体的实施方面,我们有两种策略可供选择:1) SAML 2.0 ; 2) OAuth 2.0。接下来我们区别这两种授权方式有什么不同。
但是在描述不同的策略之前,我们先叙述几个共有的,并且相当重要的概念。
Authentication VS Authorisation

Authentication: 身份鉴别,以下简称认证
Authorisation: 授权

认证的作用在于认可你有权限访问系统,用于鉴别访问者是否是合法用户;而授权用于决定你有访问哪些资源的权限。大多数人不会区分这两者的区别,因为站在用户的立场上。而作为系统的设计者来说,这两者是有差别的,这是不同的两个工作职责,我们可以只需要认证功能,而不需要授权功能,甚至不需要自己实现认证功能,而借助 Google 的认证系统,即用户可以用 Google 的账号进行登陆。

OAuth 2.0

我们先简单了解 SSO 下的 OAuth 2.0 的流程。
用户通过客户端(可以是浏览器也可以是手机应用)想要访问 SP 上的资源,但是 SP 告诉用户需要进行认证,将用户重定向至 IdP
IdP 向用户询问 SP 是否可以访问用户信息,如果用户同意,IdP 向客户端返回 access code
客户端拿 code 向 IdP 换 access token,并拿着 access token 向 SP 请求资源
SP 接受到请求之后拿着附带 token 向 IdP 验证用户的身份

那么 OAuth 是如何避免 SAML 流程下无法解析 POST 内容的信息的呢?用户从 IdP 返回客户端的方式是通过 URL 重定向,这里的 URL 允许自定义schema,所以即使在手机上也能拉起应用;另一方面因为 IdP 向客户端传递的是 code,而不是 XML 信息,所以 code 可以很轻易的附着在重定向 URL 上进行传递。

JWT

首先我们需要从感性上认识 JWT。本质上来说 JWT 也是 token,正如我们第一小节学习到的,它是访问资源的凭证
Google 的一些 API 诸如 Prediction API 或者 Google Cloud Storage,是不需要访问用户的个人数据的,因而不需要经过用户的授权这一步骤,应用程序可以直接访问。就像上一节 OAuth 中没有 Client 没有参与的流程类似。这就要借助 JWT 完成访问了, 具体流程如下:
首先你需要再 Google API 上创建一个服务账号(service account)
获取服务账号的认证信息(credential),包括邮箱地址,client ID,以及一对公钥/私钥
使用 client ID 和私钥创一个签名的 JWT,然后将这个 JWT 发送给 Google 交换 access token
Google 返回 access token
程序通过 access token 访问 API

JWT 顾名思义,它是 JSON 结构的 token,由三部分组成:1) header 2) payload 3) signature
header
header 用于描述元信息,例如产生 signature 的算法:

{
    "typ": "JWT",
    "alg": "HS256"
}

其中alg关键字就指定了使用哪一种哈希算法来创建 signature
payload
payload 用于携带你希望向服务端传递的信息。你既可以往里添加官方字段(这里的“字段” (field) 也可以被称作“声明” claims),例如iss(Issuer), sub(Subject), exp(Expiration time),也可以塞入自定义的字段,比如 userId:

{
    "userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}

signature
signature 译为「签名」
创建签名要分以下几个步骤:

你需要从接口服务端拿到密钥,假设为secret
将header进行 base64 编码,假设结果为headerStr
将payload进行 base64 编码,假设结果为payloadStr
将headerStr和payloadStr用.字符串拼装起来成为字符data
以data和secret作为参数,使用哈希算法计算出签名
如果上述描述还不直观,用伪代码表示就是:

// signature algorithm
data = base64urlEncode( header ) + “.” + base64urlEncode( payload )
signature = Hash( data, secret );

by the why
Python 有一个 jwt 包,可以直接根据一个json生成 jwt token

import jwt
token = jwt.encode(meta, '').decode()

假设我们的原始 JSON 结构是这样的:

// Header
{
  "typ": "JWT",
  "alg": "HS256"
}
// Payload:
{
  "userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}

如果密钥是字符串secret的话,那么最终 JWT 的结果就是这样的

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM

JWT 究竟带来了什么

JWT 的目的不是为了隐藏或者保密数据,而是为了确保数据确实来自被授权的人创建的(不被篡改)
回想一下,当你拿到 JWT 时候,你完全可以在没有 secret 的情况下解码出 header 和 payload,因为 header 和 payload 只是经过了 base64 编码(encode)而已,编码的目的在于利于数据结构的传输。虽然创建 signature 的过程近似于加密 (encrypt),但本质其实是一种签名 (sign) 的行为,用于保证数据的完整性,实际上也并且并没有加密任何数据
用于接口调用
接下来在 API 调用中就可以附上 JWT (通常是在 HTTP Header 中)。又因为 SP 会与程序共享一个 secret,所以后端可以通过 header 提供的相同的 hash 算法来验证签名是否正确,从而判断应用是否有权力调用 API
有状态的对话
因为 HTTP 是无状态的,所以客户端和服务端需要解决的如何让之间的对话变得有状态。例如只有是登陆状态的用户才有权限调用某些接口,那么在用户登陆之后,需要记住该用户是已经登陆的状态。常见的方法是使用 session 机制
常见的 session 模型是这样工作的:

  • 用户在浏览器登陆之后,服务端为用户生成唯一的 session id,存储在服务端的存储服务(例如 MySql, Redis)中
  • 该 session id 也同时返回给浏览器,以 SESSION_ID 为 KEY 存储在浏览器的 cookie 中
  • 如果用户再次访问该网站,cookie 里的 SESSION_ID 会随着请求一同发往服务端
    服务端通过判断 SESSION_ID 是否已经在 Redis 中判断用户是否处于登陆状态

相信你已经察觉了,理论上来说,JWT 机制可以取代 session 机制。用户不需要提前进行登陆,后端也不需要 Redis 记录用户的登陆信息。客户端的本地保存一份合法的 JWT, 当用户需要调用接口时,附带上该合法的 JWT,每一次调用接口,后端都使用请求中附带的 JWT 做一次合法性的验证。这样也间接达到了认证用户的目的。

转自关于JWT 和Token

标签:Google,JWT,token,用户,access,Token,API,关于
来源: https://www.cnblogs.com/hi3254014978/p/16559523.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有