HTTP API 授权认证有哪些方式?(Authoration, Authentication)

1.用什么方式记录登录状态?

在刚开始进行java web 开发时我们会使用基于session 的登录认证机制,会将一个 sessionId 保存到cookie 中,后端则保存对应的会话在session 中。

后来在开发前后端分离或app 接口时,登录成功后后端会生成一个uuid token 返回给前端,每次请求通过参数传递给后端,在后端将传过来的token 与保存在内存,数据库或redis中的token 进行比对相同则表示认证通过。我就会想这是不是最好的方式,或者这是不是其他人也在用的方式,这就是我写这篇文章的初衷,如果有其他或更好的方案希望能多多交流,如有错误请多指正。

  • Basic Authentication
  • Digest Authentication
  • JWT (Json Web Tokens)
  • OAuth2
  • 其他方式

2. Basic Authentication

这是 HTTP 基本授权,定义在 RFC 2617 中。
在每次请求时都需要传递一个 HTTP HEADER 例如

    
Authorization: Basic <credentials>  
    

credentials 为用户名拼接上一个冒号再加上密码,再对整个字符串进行 Base64编码

Authorization: Basic Base64(username:password)  

服务端在未授权时返回 HTTP 401 及如下 HTTP HEADER

WWW-Authenticate: Basic realm="User Visible Realm"

这时浏览器会自动弹出一个输入用户名密码的对话框,不需要任何登录界面

这种授权方式每次请求都需要传递用户名密码,而且Base64编码是可逆的,所以等于是明文传递密码,非常的不安全,只适合内部简单应用或必须在 HTTPS 下使用。

3. Digest Authentication

这是 HTTP 数字授权,定义在 RFC 2069中,后来在RFC 2617中被重新定义,比 Basic Auth 还要早,此方法适用了数字签名的方式保护了信息的安全性,具体步骤如下

首先请求服务器地址,不带任何参数,例如

GET /dir/index.html HTTP/1.0
Host: localhost

服务器会返回如下 401 未授权信息

HTTP/1.0 401 Unauthorized
Server: HTTPd/0.9
Date: Sun, 10 Apr 2014 20:26:47 GMT
WWW-Authenticate: Digest realm="testrealm@host.com",
                        qop="auth,auth-int",
                        nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                        opaque="5ccc069c403ebaf9f0171e9517f40e41"
Content-Type: text/html
Content-Length: 153

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Error</title>
  </head>
  <body>
    <h1>401 Unauthorized.</h1>
  </body>
</html>

随后客户端需要利用 WWW-Authenticate header 中的信息进行签名,默认使用 MD5 散列算法(根据服务器返回的参数签名方式有可能会有微小的区别 具体请参考 维基百科中的介绍)

HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:HA2)

并请求如下

GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Mufasa",
                     realm="testrealm@host.com",
                     nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                     uri="/dir/index.html",
                     qop=auth,
                     nc=00000001,
                     cnonce="0a4f113b",
                     response="6629fae49393a05397450978507c4ef1",
                     opaque="5ccc069c403ebaf9f0171e9517f40e41"

这种方式应该算是比较安全,可以有效的防止重放攻击,但是比较繁琐,每次请求都要先获取 nonce 随机参数并进行签名,比较适合请求量较小安全需求较高的接口使用

4. JWT (Json Web Tokens)

JWT 是基于开源标准(RFC 7519)自包含紧凑的通过json 传递安全信息的一种方式,因为它使用了数字签名所以可以被信任,JWTs 可以使用带密钥的数字签名(例如HMAC)或者非对称密钥对(RSA 或者 ECDSA)进行签名,因为不需要存储所以在分布式以及集群服务的应用中不会有单点数据节点的问题,而且不去要频繁的查询只是需要频繁的验证签名

JWT 由三个部分组成

  • Header
  • Payload
  • Signature

Header

定义token类型(typ)及签名方式(alg 设置为 HSMAC 或者 RSA)

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

Payload

在这里可以包含一些可供用的信息如下,或者 exp(过期时间),aud(受众)或其他

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Signature

secret 为保存在服务端的密钥,拼接字符串并生成签名

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

完整的 JWT

对三组字符串进行 base64 url 编码并且用 “.”链接在一起


  base64UrlEncode(header) + "." +
  base64UrlEncode(payload) + "." + 
  base64UrlEncode(Signature)
jwt

一般建议将 JWT 作为 Bearer token 通过 Authorization header 传递给服务器

Authorization: Bearer <token>   

JWT 相对于 随机数 token 有一些优势,比如token 中可以自包含一些信息,还有在服务端不需要保存token,只需要使用相同的密钥进行验证签名就可以相信token 中的内容,但是为了保证其安全性需要设置较短的失效时间建议设置为 15分钟,这会导致需要频繁获取token 的问题发生,token 的刷新及失效还有在客户端中如何保存的具体实践可以参考这篇文章 The Ultimate Guide to handling JWTs on frontend clients (GraphQL)

5. OAuth2

如果大家对接过第三方登录,那应该就有了解过 OAuth,因为最新的 OAuth版本为 2.0 并且与 1.0并不是向后兼容,而且使用OAuth2协议的比较多在这里就介绍一下 OAuth2(RFC 6749) 如果想了解 1与2的区别可以阅读这篇文章 What’s the difference between OAuth 1.0 and OAuth 2.0

在OAuth2 中主要分为 4个角色,下面使用微信第三方登录来举例进行说明

  • resource owner

资源拥有者,微信账号拥有者即用户,他希望在第三方平台使用 微信账号进行登录

  • resource server

资源服务器,微信资源服务器,保存着资源拥有者的信息,包括微信头像,微信名等等信息

  • client(consumer)

客户端,消费者,对接了微信登录的平台,需要得到授权并获取微信用户的信息

  • authorization server

授权认证服务器,微信登录认证服务器,可以给第三方平台授权

下面是简易协议流程

Protocol Flow

(A) client 向 resource owner 所求认证(吊起微信 app 请求获取 code)

(B) resource owner 返回给 client grant(认证凭证)(在微信中是个 code)

(C) client 使用 grant 向 authorization 请求 access token(使用在微信平台登记的 appId,密钥,code 进行签名后向微信授权服务器请求)

(D) authorization 返回给 client access_token(在微信中可能还包含 openId,refresh_token 等等)

(E) client 使用 access_token 获取 resource server 中的资源(使用access_token 和 openId 获取微信头像等信息)

(F) resource server 返回给 client 资源(微信资源服务器返回给第三方平台 微信用户数据)

这只是大体的一个流程,在流程 A 中如果未登录微信则还需要重定向到登录页面等的流程,在流程 B 中的 grant 也会分很多种,access_token 的实现细节也可以有多种,这些细节可以参考 RFC 或者其他文章的详细介绍

OAuth2 一般应用在第三方登录,第三方数据获取等方面,也可以实现多系统的单点登录,掌握这个协议应该是非常有用的。

6. 其他方式

还有很多第三方 Server—to-Server API 的认证机制是使用 appId 以及 appSecret 和其他参数哈希签名或非对称加密的方式,此类API 并没有使用已有的安全协议,只要appId 与 appSecret 不被泄漏应该也是比较安全的方式。

还有在 mobile api 接口中常用的uuid token 也是经常用的方式,只要保证 token 的安全也并没有太大的问题,只是相对于 jwt 没有什么优势。

7. 参考

维基百科:https://www.wikipedia.org

JWT: https://jwt.io

IETF Tools:https://tools.ietf.org

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容