在HTTP接口调用的时候,服务端经常需要对调用方做认证,以保证安全性。一种常见的认证方式是使用JWT(Json Web Token),采用这种方式时,经常在header传入一个authorization字段,值为对应的jwt_token,或者也有图方便直接写在json中这种用法。本篇博文简单介绍一下jwt认证。本文大体翻译自jwt官网介绍,也参考了一些其他内容。
JSON Web Token (JWT) 是一个开源标准(RFC 7519),它定义了一种紧凑且自完备的方法用于在各参与方之间以JSON对象传递信息。以该种方式传递的信息已经被数字签名,因而可以被验证并且被信任。JWT既可以使用盐(secret)(HMAC算法)进行签名,也可以使用基于RSA/ECDSA算法的公钥/秘钥对进行签名。
紧凑翻译自compact,至于为什么这么翻译,看完你就懂了。
认证:认证是JWT的最常用场景。只要用户完成登录,其随后的请求都会包含JWT,以允许用户访问经由当前JWT授权的路由、服务或者是资源。由于开销小且能够被简单应用在跨域访问上,JWT在分布式站点上所支持的单点登录(SSO)已经是当前它被广泛应用的一个特性。
信息交换:JWT是一种在各参与方之间安全传递信息的良好方法。由于JWT可以被签名(例:使用公钥/秘钥对),因而可用于确认发送者自称的身份。除此之外,由于signature使用header和payload进行计算,也可以验证内容没有被篡改。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
在紧凑形式下,Json Web Token由以下三部分组成:
因此,一个典型的JWT形式如:xxx.yyy.zzz
,由两个点.
间隔。
典型的JWT header包含两个部分:(1) token类型,即JWT。(2) 所使用的签名算法,比如HMAC SHA256或者RSA。
例:
{
"alg": "HS256",
"typ": "JWT"
}
该JSON以Base64Url加密(可以被对称解密)后形成了JWT的第一部分:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
JWT token的第二部分是包含了声明的payload,声明是一个实体的表述加上额外信息,一共有三种形式的声明:注册、共有和私有。
定义一个payload:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对其进行base64加密,得到JWT的第二部分:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
JWT的第三部分是签名信息,Signature由三部分组成:
Signature需要将base64加密后的header和payload使用.
连接,然后通过header所使用的加密方式进行加盐(secret)组合加密,产生了jwt的第三部分。以使用HMAC SHA256算法为例,signature以如下方式产生:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Signature被用于验证信息在传输过程中没有被更改,或者在token以私钥加密的条件下,也可以验证JWT的发送者是否是其所自称的身份。
注:secret保存在服务端,jwt的签发也发生在服务端,secret即是用来进行jwt的签发和验证的。因为,它就是服务端的私钥,任何场景下都不应该被泄露出去。
在认证(authentication)过程中,当用户使用凭据成功登录后,就会返回一个jwt token。因为jwt token是一种凭据,必须仔细关注其安全问题。一般而言,需要讲token的长度限制在需要的范围内。
也不应该在浏览器中存储敏感的session信息,因为这样缺乏安全。
每当用户希望访问一个被保护的路由或者资源,用户代理应当发送JWT,典型的用法是加上Authorization
header并使用Bear模式。Header的内容如下:
Authorization: Bearer <token>
在某些情况下,这是一种无状态授权方式。服务器的受保护路由会检查Authorization
header中的jwt token是否有效,如果该token是存在的,那么用将被允许访问受保护资源。如果JWT包含了必要数据,某些操作下的查库需要会被省去,尽管这种情况不是一定的。
注:如果采用HTTP headers发送jwt token,应该避免它的体积变得很大。一些服务器不接收大于8KB的header。如果你一定要在一个jwt token中嵌入大量信息,例如包含用户全部的授权信息,你可能需要其他解决方案,比如: Auth0 Fine-Grained Authorization
如果token使用Authorization
发送,跨源资源共享(Cross-Origin Resource Sharing, CORS)将不再是问题,因为jwt不需要使用cookies
。
下图展示了一个JWT token被获取并被用于访问API或者资源的过程:
/oauth/authorize
终端进行请求。基于cookie的认证,存在如下问题:
基于session的认证,存在如下问题:
JWT是一种基于token的认证机制,它类似于HTTP协议一样是无状态的,不需要在服务端保留用户的认证信息或者会话信息。除此之外,基于token的鉴权机制不需要考虑用户在哪一台服务器登录,为应用扩展提供了便利。
接下来我们对比一下JWT和SWT(Simple Web Token)以及Security Assertion Markup Language Tokens (SAML),两者都是基于token的鉴权机制。
由于JSON没有XML那么冗余,被编码时体积也更小,因而JWT比SAML更紧凑。这使得JWT成为一个在HTML和HTTP环境下传递信息的最佳选择。
安全方面,SWT仅能被共享盐(shared secret)对称加密,但是JWT和SAML能被公钥/私钥对已X.509
证书签名。相较于对JSON进行签名的简洁,处理XML时在没有引入隐秘安全漏洞前提下进行数字签名是一件非常困难的事。
在众多编程语言中JSON解析器都是常见的,因为可以直接映射对象。相反,XML则没有一个自然的文档to对象映射。这使得JWT比SAML断言使用起来更加简单。
应用方面,JWT已经在互联网层面广泛应用。JSON Web token在众多平台上客户端侧的简单处理尤为出彩,尤其是移动端。
再补充一些jwt的优点:
安全方面应该注意的点:
什么是 JWT – JSON WEB TOKEN
官网介绍:Introduction to JSON Web Tokens
基于jwt和session用户认证的区别和优缺点