GHOST系统之家 - Windows系统光盘下载网站!
当前位置:GHOST系统之家>电脑问题 > 前后端分离开发,HTTP API 认证授权术

前后端分离开发,HTTP API 认证授权术

来源:Ghost系统之家浏览:时间:2022-12-09 17:44:40

我们知道,HTTP是无状态的,所以,当我们需要获得用户是否在登录的状态时,我们需要检查用户的登录状态,一般来说,用户的登录成功后,服务器会发一个登录凭证(又被叫作Token),就像你去访问某个公司,在前台被认证过合法后,这个公司的前台会给你的一个访客卡一样,之后,你在这个公司内去到哪都用这个访客卡来开门,而不再校验你是哪一个人。在计算机的世界里,这个登录凭证的相关数据会放在两种地方,一个地方在用户端,以Cookie的方式(一般不会放在浏览器的 Local Storage,因为这很容易出现登录凭证被 XSS 攻击),另一个地方是放在服务器端,又叫Session的方式(SessonID 存于 Cookie)。

但是,这个世界还是比较复杂的,除了用户访问,还有用户委托的第三方的应用,还有企业和企业间的调用,这里,我想把业内常用的一些API认证技术相对系统地总结归纳一下,这样可以让大家更为全面的了解这些技术。注意,这是一篇长文!

本篇文章会覆盖如下技术:

  • HTTP Basic
  • Digest Access
  • App Secret Key + HMAC
  • JWT – JSON Web Tokens
  • OAuth 1.0 – 3 legged & 2 legged
  • OAuth 2.0 – Authentication Code & Client Credential

HTTP Basic

HTTP Basic 是一个非常传统的 API 认证技术,也是一个比较简单的技术。这个技术也就是使用 username 和password来进行登录。整个过程被定义在了 RFC 2617 中,也被描述在了 Wikipedia: Basic AccessAuthentication词条中,同时也可以参看 MDN HTTP Authentication

其技术原理如下:

我们可以看到,使用 Base64 的目的无非就是为了把一些特殊的字符给搞掉,这样就可以放在HTTP协议里传输了。而这种方式的问题最大的问题就是把用户名和口令放在网络上传,所以,一般要配合 TLS/SSL 的安全加密方式来使用。我们可以看到JIRACloud 的 API 认证支持HTTP Basic 这样的方式。

但我们还是要知道,这种把用户名和密码同时放在公网上传输的方式有点不太好,因为 Base64 不是加密协议,而是编码协议,所以就算是有HTTPS作为安全保护,给人的感觉还是不放心。

Digest Access

中文称“HTTP 摘要认证”,最初被定义在了 RFC 2069 文档中(后来被 RFC2617引入了一系列安全增强的选项;“保护质量”(qop)、随机数计数器由客户端增加、以及客户生成的随机数)。

其基本思路是,请求方把用户名口令和域做一个 MD5 –MD5(username:realm:password)然后传给服务器,这样就不会在网上传用户名和口令了,但是,因为用户名和口令基本不会变,所以,这个MD5的字符串也是比较固定的,因此,这个认证过程在其中加入了两个事,一个是 nonce 另一个是 qop

  • 首先,调用方发起一个普通的 HTTP 请求。比如:GET /coolshell/admin/ HTTP/1.1 服务端自然不能认证能过,服务端返回 401错误,并且在 HTTP 头里的 WWW-Authenticate 包含如下信息:

  • 其中的 nonce 为服务器端生成的随机数,然后,客户端做HASH1=MD5(MD5(username:realm:password):nonce:cnonce) ,其中的 cnonce为客户端生成的随机数,这样就可以使得整个 MD5 的结果是不一样的。

  • 如果 qop 中包含了 auth ,那么还得做 HASH2=MD5(method:digestURI) 其中的 method就是HTTP的请求方法(GET/POST…),digestURI 是请求的URL。
  • 如果 qop 中包含了 auth-init ,那么,得做 HASH2=MD5(method:digestURI:MD5(entityBody)) 其中的entityBody 就是HTTP请求的整个数据体。
  • 然后,得到 response = MD5(HASH1:nonce:nonceCount:cnonce:qop:HASH2) 如果没有 qop 则response = MD5(HA1:nonce:HA2)
  • 最后,我们的客户端对服务端发起如下请求—— 注意HTTP头的 Authorization: Digest ...

维基百科上的 Wikipedia: Digest access authentication 词条非常详细地描述了这个细节。

摘要认证这个方式会比之前的方式要好一些,因为没有在网上传递用户的密码,而只是把密码的 MD5 传送过去,相对会比较安全,而且,其并不需要是否TLS/SSL的安全链接。但是,别看这个算法这么复杂,最后你可以发现,整个过程其实关键是用户的 password,这个password如果不够得杂,其实是可以被暴力破解的,而且,整个过程是非常容易受到中间人攻击——比如一个中间人告诉客户端需要的 Basic 的认证方式或是老旧签名认证方式(RFC2069)。

App Secret Key + HMAC

先说 HMAC 技术,这个东西来自于 MAC – MessageAuthenticationCode,是一种用于给消息签名的技术,也就是说,我们怕消息在传递的过程中被人修改,所以,我们需要用对消息进行一个MAC算法,得到一个摘要字串,然后,接收方得到消息后,进行同样的计算,然后比较这个 MAC 字符串,如果一致,则表明没有被修改过(整个过程参看下图)。而HMAC –Hash-based Authenticsation Code,指的是利用 Hash 技术完成这一工作,比如:SHA-256算法。

我们再来说 App ID,这个东西跟验证没有关系,只是用来区分,是谁来调用API的,就像我们每个人的身份证一样,只是用来标注不同的人,不是用来做身份认证的。与前面的不同之处是,这里,我们需要用 AppID来映射一个用于加密的密钥,这样一来,我们就可以在服务器端进行相关的管理,我们可以生成若干个密钥对(AppID,AppSecret),并可以有更细粒度的操作权限管理。

最后,发出 HTTP Request 时,在 HTTP 头的 Authorization 字段中放入如下的信息:

其中的 AKIDEXAMPLE 是 AWS Access Key ID, 也就是所谓的 AppID,服务器端会根据这个 AppID 来查相关的SecretAccess Key,然后再验证签名。如果,你对这个过程有点没看懂的话,你可以读一读这篇文章——《Amazon S3 Rest APIwithcurl》这篇文章里有好些代码,代码应该是最有细节也是最准确的了。

这种认证的方式好处在于,AppID 和 AppSecretKey,是由服务器的系统开出的,所以,是可以被管理的,AWS 的IAM就是相关的管理,其管理了用户、权限和其对应的 AppID和AppSecretKey。但是不好的地方在于,这个东西没有标准,所以,各家的实现很不一致。比如:Acquia 的 HMAC,微信的签名算法(这里,我们需要说明一下,微信的 API 没有遵循HTTP协议的标准,把认证信息放在 HTTP 头的 Authorization 里,而是放在 body里)

JWT – JSON Web Tokens

JWT 是一个比较标准的认证解决方案,这个技术在 Java 圈里应该用的是非常普遍的。JWT 签名也是一种MAC(MessageAuthentication Code)的方法。JWT 的签名流程一般是下面这个样子:

用户使用用户名和口令到认证服务器上请求认证。

认证服务器验证用户名和口令后,以服务器端生成 JWT Token,这个 token 的生成过程如下:

  • 认证服务器还会生成一个 Secret Key(密钥)
  • 对JWT Header和 JWT Payload 分别求 Base64。在 Payload 可能包括了用户的抽象 ID 和的过期时间。
  • 用密钥对 JWT 签名 HMAC-SHA256(SecertKey,Base64UrlEncode(JWT-Header)+'.'+Base64UrlEncode(JWT-Payload));

然后把 base64(header).base64(payload).signature 作为 JWT token 返回客户端。

客户端使用 JWT Token 向应用服务器发送相关的请求。这个 JWT Token 就像一个临时用户权证一样。

当应用服务器收到请求后:

我们可以看以,上面的这个过程,是在认证服务器上为用户动态生成 SecretKey的,应用服务在验签的时候,需要到认证服务器上去签,这个过程增加了一些网络调用,所以,JWT 除了支持 HMAC-SHA256 的算法外,还支持RSA的非对称加密的算法。

使用RSA非对称算法,在认证服务器这边放一个私钥,在应用服务器那边放一个公钥,认证服务器使用私钥加密,应用服务器使用公钥解密,这样一来,就不需要应用服务器向认证服务器请求了,但是,RSA是一个很慢的算法,所以,虽然你省了网络调用,但是却费了CPU,尤其是Header 和 Payload 比较长的时候。所以,一种比较好的玩法是,如果我们把header 和 payload 简单地做SHA256,这会很快,然后,我们用 RSA 加密这个 SHA256 出来的字符串,这样一来,RSA算法就比较快了,而我们也做到了使用 RSA 签名的目的。

最后,我们只需要使用一个机制在认证服务器和应用服务器之间定期地换一下公钥私钥对就好了。

这里强烈建议全文阅读 Anglar 大学的 《JSW:The Complete Guide to JSON Web Tokens》

OAuth 1.0

OAuth 也是一个 API 认证的协议,这个协议最初在 2006 年由 Twitter 的工程师在开发 OpenID实现的时候和社交书签网站Ma.gnolia 时发现,没有一种好的委托授权协议,后来在 2007 年成立了一个 OAuth小组,知道这个消息后,Google员工也加入进来,并完善有善了这个协议,在 2007 年底发布草案,过一年后,在 2008 年将 OAuth 放进了IETF 作进一步的标准化工作,最后在2010 年 4 月,正式发布 OAuth 1.0,即:RFC 5849 (这个 RFC 比起TCP的那些来说读起来还是很轻松的),不过,如果你想了解其前身的草案,可以读一下 OAuth Core 1.0 RevisionA,我在下面做个大概的描述。

根据RFC 5849,可以看到OAuth的出现,目的是为了,用户为了想使用一个第三方的网络打印服务来打印他在某网站上的照片,但是,用户不想把自己的用户名和口令交给那个第三方的网络打印服务,但又想让那个第三方的网络打印服务来访问自己的照片,为了解决这个授权的问题,OAuth这个协议就出来了。

这个协议有三个角色:

  • User(照片所有者-用户)
  • Consumer(第三方照片打印服务)
  • Service Provider(照片存储服务)

这个协义有三个阶段:

  • Consumer 获取 Request Token
  • Service Provider 认证用户并授权 Consumer
  • Consumer 获取 Access Token 调用 API 访问用户的照片

整个授权过程是这样的:

下图附上一个 Yahoo! 的流程图可以看到整个过程的相关细节。

因为上面这个流程有三方:User,Consumer 和 Service Provide,所以,又叫 3-legged flow,三脚流程。OAuth1.0也有不需要用户参与的,只有 Consumer 和 Service Provider 的, 也就是 2-leggedflow两脚流程,其中省掉了用户认证的事。整个过程如下所示:

最后,再来说一说 OAuth 中的签名。

  • 我们可以看到,有两个密钥,一个是 Consumer 注册 Service Provider 时由 Provider 颁发的 ConsumerSecret,另一个是 Token Secret。
  • 签名密钥就是由这两具密钥拼接而成的,其中用 & 作连接符。假设 Consumer Secret 为 j49sk3j29djd 而 TokenSecret 为 dh893hdasih9 那个,签名密钥为:j49sk3j29djd&dh893hdasih9
  • 在请求 Request/Access Token 的时候需要对整个 HTTP 请求进行签名(使用 HMAC-SHA1 和 HMAC-RSA1签名算法),请求头中需要包括一些 OAuth 需要的字段,如:
    • Consumer Key :也就是所谓的 AppID
    • Token:Request Token 或 Access Token
    • Signature Method :签名算法比如:HMAC-SHA1
    • Timestamp:过期时间
    • Nonce:随机字符串
    • Call Back:回调 URL

下图是整个签名的示意图:

图片还是比较直观的,我就不多解释了。

OAuth 2.0

在前面,我们可以看到,从 Digest Access, 到 AppID+HMAC,再到 JWT,再到 OAuth 1.0,这些个 API认证都是要向Client发一个密钥(或是用密码)然后用 HASH 或是 RSA 来签 HTTP 的请求,这其中有个主要的原因是,以前的HTTP是明文传输,所以,在传输过程中很容易被篡改,于是才搞出来一套的安全签名机制,所以,这些个认证的玩法是可以在 HTTP 明文协议下玩的。

这种使用签名方式大家可以看到是比较复杂的,所以,对于开发者来说,也是很不友好的,在组织签名的那些 HTTP 报文的时候,各种,URLEncode和Base64,还要对Query的参数进行排序,然后有的方法还要层层签名,非常容易出错,另外,这种认证的安全粒度比较粗,授权也比较单一,对于有终端用户参与的移动端来说也有点不够。所以,在2012年的时候,OAuth 2.0 的 RFC 6749 正式放出。

OAuth 2.0 依赖于 TLS/SSL 的链路加密技术(HTTPS),完全放弃了签名的方式,认证服务器再也不返回什么 tokensecret的密钥了,所以,OAuth 2.0 是完全不同于 1.0 的,也是不兼容的。目前,Facebook 的 Graph API 只支持OAuth2.0协议,Google 和 Microsoft Azure 也支持Auth 2.0,国内的微信和支付宝也支持使用 OAuth 2.0。

下面,我们来重点看一下 OAuth 2.0 的两个主要的 Flow:

  • 一个是 Authorization Code Flow, 这个是 3 legged 的
  • 一个是 Client Credential Flow,这个是 2 legged 的。

Authorization Code Flow

Authorization Code 是最常使用的 OAuth 2.0 的授权许可类型,它适用于用户给第三方应用授权访问自己信息的场景。这个 Flow也是OAuth 2.0 四个 Flow 中我个人觉得最完整的一个 Flow,其流程图如下所示。

下面是对这个流程的一个细节上的解释:

1)当用户(ResourceOwner)访问第三方应用(Client)的时候,第三方应用会把用户带到认证服务器(AuthorizationServer)上去,主要请求的是/authorize API,其中的请求方式如下所示。

其中:

  • client_id 为第三方应用的 App ID
  • response_type=code 为告诉认证服务器,我要走 Authorization Code Flow。
  • redirect_uri 意思是我跳转回第三方应用的 URL
  • scope 意是相关的权限
  • state 是一个随机的字符串,主要用于防 CSRF 攻击。

2)当 Authorization Server 收到这个 URL 请求后,其会通过 client_id 来检查 redirect_uri 和scope是否合法,如果合法,则弹出一个页面,让用户授权(如果用户没有登录,则先让用户登录,登录完成后,出现授权访问页面)。

3)当用户授权同意访问以后,Authorization Server 会跳转回 Client ,并以其中加入一个AuthorizationCode。如下所示:

我们可以看到,

  • 请流动的链接是第 1)步中的 redirect_uri
  • 其中的 state 的值也和第 1)步的 state一样。

4)接下来,Client 就可以使用 Authorization Code 获得 Access Token。其需要向 AuthorizationServer发出如下请求。

5)如果没什么问题,Authorization 会返回如下信息。

其中,

  • access_token 就是访问请求令牌了
  • refresh_token 用于刷新 access_token
  • id_token 是 JWT 的 token,其中一般会包含用户的 OpenID

6)接下来就是用 Access Token 请求用户的资源了。

Client Credential Flow

Client Credential 是一个简化版的 API认证,主要是用于认证服务器到服务器的调用,也就是没有用户参与的的认证流程。下面是相关的流程图。

这个过程非常简单,本质上就是 Client 用自己的 client_id 和 client_secret 向Authorization Server要一个Access Token,然后使用 Access Token 访问相关的资源。

请求示例

返回示例

这里,容我多扯一句,微信公从平台的开发文档中,使用了 OAuth 2.0 的 Client Credentials的方式(参看文档“微信公众号获取access token”),我截了个图如下所谓。我们可以看到,微信公众号使用的是 GET 方式的请求,把 AppID 和AppSecret 放在了URL中,虽然这也符合 OAuth 2.0,但是并不好,因为大多数网关代理会把整个 URI请求记到日志中。我们只要脑补一下腾讯的网关的 AccessLog,里面的日志一定会有很多的各个用户的AppID 和 AppSecret……

小结

讲了这么多,我们来小结一下(下面的小结可能会有点散)

两个概念和三个术语

  • 区分两个概念:Authentication(认证) 和 Authorization(授权),前者是证明请求者是身份,就像身份证一样,后者是为了获得权限。身份是区别于别人的证明,而权限是证明自己的特权。Authentication为了证明操作的这个人就是他本人,需要提供密码、短信验证码,甚至人脸识别。Authorization 则是不需要在所有的请求都需要验人,是在经过Authorization 后得到一个 Token,这就是 Authorization。就像护照和签证一样。
  • 区分三个概念:编码 Base64Encode、签名 HMAC、加密RSA。编码是为了更的传输,等同于明文,签名是为了信息不能被篡改,加密是为了不让别人看到是什么信息。

明白一些初衷

  • 使用复杂地 HMAC 哈希签名方式主要是应对当年没有 TLS/SSL 加密链路的情况。
  • JWT 把 uid 放在 Token 中目的是为了去掉状态,但不能让用户修改,所以需要签名。
  • OAuth 1.0 区分了两个事,一个是第三方的 Client,一个是真正的用户,其先拿 Request Token,再换 Access Token的方法主要是为了把第三方应用和用户区分开来。
  • 用户的 Password 是用户自己设置的,复杂度不可控,服务端颁发的 Serect 会很复杂,但主要目的是为了容易管理,可以随时注销掉。
  • OAuth 协议有比所有认证协议有更为灵活完善的配置,如果使用 AppID/AppSecret签名的方式,又需要做到可以有不同的权限和可以随时注销,那么你得开发一个像 AWS 的 IAM 这样的账号和密钥对管理的系统。

相关的注意事项

  • 无论是哪种方式,我们都应该遵循 HTTP 的规范,把认证信息放在 Authorization HTTP 头中。
  • 不要使用 GET 的方式在 URL 中放入 secret 之类的东西,因为很多 proxy 或 gateway 的软件会把整个 URL 记在 AccessLog 文件中。
  • 密钥 Secret 相当于 Password,但他是用来加密的,最好不要在网络上传输,如果要传输,最好使用 TLS/SSL 的安全链路。
  • HMAC 中无论是 MD5 还是 SHA1/SHA2,其计算都是非常快的,RSA 的非对称加密是比较耗 CPU的,尤其是要加密的字符串很长的时候。
  • 最好不要在程序中 hard code 你的 Secret,因为在 github 上有很多黑客的软件在监视各种Secret,千万小心!这类的东西应该放在你的配置系统或是部署系统中,在程序启动时设置在配置文件或是环境变量中。
  • 使用 AppID/AppSecret,还是使用 OAuth1.0a,还是 OAuth2.0,还是使用 JWT,我个人建议使用 TLS/SSL 下的OAuth 2.0。
  • 密钥是需要被管理的,管理就是可以新增可以撤销,可以设置账户和相关的权限。最好密钥是可以被自动更换的。
  • 认证授权服务器(Authorization Server)和应用服务器(App Server)最好分开。

推荐系统

  • 微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    语言:中文版系统大小:5.13GB系统类型:Win11

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Win11 64位 Office办公版(免费)优化  1、保留 Edge浏览器。  2、隐藏“操作中心”托盘图标。  3、保留常用组件(微软商店,计算器,图片查看器等)。  5、关闭天气资讯。 

  • Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    语言:中文版系统大小:4.75GB系统类型:Win11

    Ghost Win11 21H2是微软在系统方面技术积累雄厚深耕多年,Ghost Win11 21H2系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Ghost Win11 21H2是微软最新发布的KB5019961补丁升级而来的最新版的21H2系统,以Windows 11 21H2 22000 1219 专业版为基础进行优化,保持原汁原味,系统流畅稳定,保留常用组件

  • windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载,微软win11发布快大半年了,其中做了很多次补丁和修复一些BUG,比之前的版本有一些功能上的调整,目前已经升级到最新版本的镜像系统,并且优化了自动激活,永久使用。windows11中文版镜像国内镜像下载地址微软windows11正式版镜像 介绍:1、对函数算法进行了一定程度的简化和优化

  • 微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载,微软2022年正式推出了win11系统,很多人迫不及待的要体验,本站提供了最新版的微软Windows11正式版系统下载,微软windows11正式版镜像 是一款功能超级强大的装机系统,是微软方面全新推出的装机系统,这款系统可以通过pe直接的完成安装,对此系统感兴趣,想要使用的用户们就快来下载

  • 微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    语言:中文版系统大小:0MB系统类型:Win11

    微软Ghost win11 正式版镜像文件是一款由微软方面推出的优秀全新装机系统,这款系统的新功能非常多,用户们能够在这里体验到最富有人性化的设计等,且全新的柔软界面,看起来非常的舒服~微软Ghost win11 正式版镜像文件介绍:1、与各种硬件设备兼容。 更好地完成用户安装并有效地使用。2、稳定使用蓝屏,系统不再兼容,更能享受无缝的系统服务。3、为

  • 雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    语言:中文版系统大小:4.75GB系统类型:

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载在系统方面技术积累雄厚深耕多年,打造了国内重装系统行业的雨林木风品牌,其系统口碑得到许多人认可,积累了广大的用户群体,雨林木风是一款稳定流畅的系统,一直以来都以用户为中心,是由雨林木风团队推出的Windows11国内镜像版,基于国内用户的习惯,做了系统性能的优化,采用了新的系统

  • 雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    语言:中文版系统大小:5.91GB系统类型:Win7

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO在系统方面技术积累雄厚深耕多年,加固了系统安全策略,雨林木风win7旗舰版系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。win7 32位旗舰装机版 v2019 05能够帮助用户们进行系统的一键安装、快速装机等,系统中的内容全面,能够为广大用户

  • 番茄花园Ghost Win7 x64 SP1稳定装机版2022年7月(64位) 高速下载

    番茄花园Ghost Win7 x64 SP1稳定装机版2022年7月(64位) 高速下载

    语言:中文版系统大小:3.91GB系统类型:Win7

    欢迎使用 番茄花园 Ghost Win7 x64 SP1 2022.07 极速装机版 专业装机版具有更安全、更稳定、更人性化等特点。集成最常用的装机软件,集成最全面的硬件驱动,精心挑选的系统维护工具,加上独有人性化的设计。是电脑城、个人、公司快速装机之首选!拥有此系统