Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[译]Introduction to JSON Web Tokens #170

Open
FrankKai opened this issue Dec 12, 2019 · 5 comments
Open

[译]Introduction to JSON Web Tokens #170

FrankKai opened this issue Dec 12, 2019 · 5 comments
Labels

Comments

@FrankKai
Copy link
Owner

  • 什么是JSON Web Token?
  • 什么时候使用JSON Web tokens?
    • 授权
    • 信息转换
  • JSON Web Token结构是什么样的?
    • Header
    • Payload
    • Signature
    • Putting all together
  • JSON Web Tokens是如何工作的?
  • 我们为什么要使用JSON Web Tokens?

https://jwt.io/introduction/

@FrankKai
Copy link
Owner Author

什么是JSON Web Token?

  • JSON Web Token(JWT)是一个开源标准(RFC 7519),它定义了一种简洁的自容器的在两个组织之间通过JSON object安全传输信息的方式
  • 这个信息是经过验证而且值得相信的,因为它是数字签名的。JWT可以通过secret(HMAC算法)签名,也可以通过public/private键对(RSA或者ECDSA)。
  • 尽管JWT可以在两个组织之间建立一种加密的信息处理,但是我们集中注意力在signedtokens上。Signed tokens可以验证包含在其中的完整性加密的tokens对于其他组织是隐藏的。
  • 当使用public/private键对给token做签名时,签名会证明只有拥有私钥的组织能做签名。

@FrankKai
Copy link
Owner Author

什么时候使用JSON Web tokens?

下面这些场景下,JSON Web Tokens是有用的:授权和信息转换。

授权

这是JWT最常用的场景。一旦用户登录进来,随后的请求都会带上JWT,允许用户获得token允许的routes,services和资源。SSO是现今广泛使用JWT的一个特性,因为其开销小,以及跨域名可以很容易实现。

信息转换

JWT是两个组织之间进行安全信息传输的很好的方式。因为JWT可以签名---例如,使用public/private键对,可以确定发送者就是他们说的那个人。除此之外,使用header和payload计算签名,可以验证内容是否被人篡改。

@FrankKai
Copy link
Owner Author

JSON Web Token结构是什么样的?

JWT的结构很简单,JSON Web Tokens由三部分组成,它们之间通过.连接。
三部分主要是:Header, Payload, Signature
因此JWT的格式就像这样:xxxxx.yyyyy.zzzzz。
现在我们一点一点去拆分每一部分。

Header

header由两部分组成:token的类型,也就是JWT;token的签名算法,可以是HMAC,SHA256和RSA。
例如:

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

编码是Base64Url格式的,作为JWT的第一部分。

Payload

token的第二部分是payload,其中包含了claims(声明)。
Claims指的是实体(典型的是user)和额外数据的语句。
有三种类型的claim:registered,public和private claim。

Registered claims

有一个预先定义好的claim集合,不是强制的但是非常推荐的,去提供有用的彼此协作的claim。其中包括,iss(issuer),exp(expiration time),sub(subject),aud(audience)和其他的。

注意:claim或者声明的名字只有3个字符长的原因,是因为JWT的目的是紧凑。

Public claims

这些可以由使用JWT的人随意定义。但是为了避免collision它们应该在IANA JSON Web Token Registry注册或者可以定义成一个URI,这个URI上包含了一个耐碰撞名称空间。

Private claims

这些是自定义的claim。两个组织之间约定好既不通过registered claim也不通过public claim,而是通过自定义的claim去分享信息。

一个payload示例如下:

{
    "sub": "1234567890",
    "name": "FrankKai",
    "admin": true
}

编码是Base64Url格式的,作为JWT的第二部分。
注意:对于签名token来说,尽管可以保护其不被篡改,但是对于所有人都是可读的。不要在payload或者JWT的header元素上存储secret information,除非是经过加密的。

Signature

为了创建编码头的signature部分,在header上需要指明编码后的payload,编码后的payload和一个secret,以及签名算法并且签名。

例如如果你想用HMAC SHA256算法,签名会按照下面的方式创建:

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

签名用于验证消息在整个过程中没有被更改,并且,对于使用私钥签名的令牌,它还可以验证JWT的发送方就是它所说的发送方。

Putting all together

输出是3个被.分离的Base64-URL字符串,可以在HTML和HTTP环境中传输,与基于XML的标准比如SAML相比,这种格式更简单。

下面的输出表示JWT的header和payload是编码过的,并且用一个secret做签名。

image

如果想体验一下JWT,可以用jwt.io Debugger去解码,验证以及生成JWT。

image

找一个自己公司的试试:
image

我司由于最近才接入了单点,经验不是很成熟,所以jwt中包含了用户密码的敏感数据。

存储在localStorage中的jwt,payload中包含了用户密码,使用https://hashkiller.co.uk/Cracker/MD5
这个网站可以成功解析出。
image

在我的沟通下,服务端做了调整。
image

image

@FrankKai
Copy link
Owner Author

JSON Web Tokens是如何工作的?

在验证时,当用户成功使用凭证登录成功以后,一个JSON Web Token会返回。因为token是凭证,必须严加保管从而避免安全问题。总的来说,不需要时就不要留着token了。

处于缺乏安全性的考虑,不要在浏览器storage存储敏感的session数据。

如果用户什么时候想获取被保护的路由或者资源,用户代理需要发送JWT,典型的场景是在Authorization header上使用Bearer字段。header的内容看起来像下面这样:

Authorization: Bearer <token>

这是一个无状态的验证机制。服务端的保护路由会在Authorization header上检查这个有效的JWT,而且如果存在的话,用户会被赋权去获得被保护的资源。如果JWT包含了必要的数据的话,为了特殊操作查询数据库的需要也许会被减少。

如果token放在Authorization header上的话,CORS没有问题,因为没有用cookie。

下面这个流程图展示了JWT是如何生成和如何从API获取资源的:
image

1.应用或者client向鉴权服务器请求鉴权。这是通过不同的授权流之一执行的。例如,一个OpenID Connect web应用会到/oauth/authorize端点使用authorization code flow。
2.当权被分配时,鉴权服务器返回一个权限token给应用。
3.应用会用access token去获取被保护的资源。(比如一个API)

注意signed tokens,在token上包含的所有信息会暴露给用户和其他组织,即使他们不能改变它。也就是说你不要在token上传递敏感信息。

备注:我们公司的内部管理系统,在jwt的payload上添加了用户密码,这样很不安全。服务端给出的处理是jwt的payload上移除用户密码;md5加密增加salt。

@FrankKai
Copy link
Owner Author

我们为什么要使用JSON Web Tokens?

Simple Web Tokens(SWT)和 Security Assertion Markup Language Tokens(SAML)也是两种token方式,我们来讨论下JSON Web Tokens(JWT)的好处。

JSON比XML更简洁,它编码以后会更小,JWT比SAML更简洁。这使得JWT成为一种HTML和HTTP环境下的很好的传输选择。

SWT可以通过HMAC算法用共享密码做对称签名。然而,JWT和SAML token用公共/私密X.509键值对格式。在和签名JSON做对比时,没有引入模糊的安全漏洞的对XML做XML数字签名是非常困难的。

JSON parsers在大多数程序语言中都是可用的,因为它们直接映射成objects。相反地,XML没有自然文档-对象映射。所以用JWT比SAML更好。

JWT在互联网上广泛应用。所以再多个平台尤其是移动端上处理JWT是非常方便的。

JWT比SAML又短又清晰

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant