Restful API 使用 JWT 安全验证
背景
参考 开放api接口签名验证 ,REST接口安全认证方式对比:API Key vs OAuth令牌 vs JWT
微服务开发过程中,写开放的API接口时,可能会带来如下安全问题:
- 请求源是否合法
- 请求参数是否被篡改
- 请求的唯一性
为了避免以上安全性问题,保证数据在通信时的安全性,我们需要验证使用者的身份。验证使用者身份有多种方式:session , token等。在微服务中,用户直接调用API获取资源,这时候就需要token来验证使用者身份,保护数据安全。这篇文章主要讲token ----json web token。
以下内容摘自 以 JSON Web Token 替代傳統 Token
session
在传统网站中,会用session来辨别使用者身份,辨别使用者是否登陆。由于session只会被服务器端知道,所以可以在session中保存一些机密资料以供之后验证使用。
session存在的问题
- 具状态性:假设有两台服务器 通过负载均衡 来互相处理 用户请求,由于session是存储在服务器端,第一次用户登陆时,由Server1 处理,那么session会存在Server1。如果下一次,用户请求 被负载均衡 指派Server2来处理,那么session在Server2不存在,所以用户就需要重新登陆一次。(这个问题可以解决,暂不讨论)
- 容易受 跨网域请求伪造攻击:session存在服务器端,所以用户 在发送请求时几乎不用提供什么。所以很可能用户提供了一个删除文章的连接给服务器,服务器就删除了文章。
Token
Token可以解决 session 容易受 跨网域请求伪造攻击的问题,并且可以在多个服务器上 跨域使用。
- 什么是token:用户登陆成功时,会得到一个数字字符串,这个串看起来毫无意义,可是对应资料库中使用者的身份。这个串就是token
- 无状态性:当服务器接收到token时,会解密token,对比数据库,然后就会知道这个token是否合法,对应哪个用户,并获取这个用户的相关资料等。由于多个服务器共享一个 数据库,所以就不存在session 只存在 在一个服务器的问题。
- 避免 受 跨网域请求伪造攻击:因为用户需要主动提供token,非法攻击 不会拥有合法的token,所以不能请求成功。
JWT json web token 取代传统token
- 相比token需要从数据库中比对用户是否合法,jwt 可以存放资料,不需要数据库来存储用户资料。直接把用户资料存放在「Token」中,所以也就省去了额外的数据库开销
JWT json web token 的构成:
- Header 头部:JWT 的头部包含两部分,token类型和采用的加密算法。这些內容通过 Base64 编码就得到JWT的头部 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
{
"alg": "HS256",
"typ": "JWT"
}
- Payload 负载:JWT的标准所定义的几个基本字段 + 我们在业务处理中需要用到的字段,如用户账号,昵称等,这样就不再需要去数据库找,不要放密码。将这部分通过 Base64 编码就得到第二段字符串 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
- JWT的标准所定义的几个基本字段
- issuer: 该JWT的签发者
- subject: 该JWT所面向的用户
- audience: 接收该JWT的一方
- expiration(expires): 什么时候过期,这里是一个Unix时间戳
- issueAt(issued at): 在什么时候签发的
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
- Signature 签名:这部分的算法是由上面两部分内容的 Base64 以點(
.
)組合起來,并以密码加密得到签名TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), "secret")
以上3部分就组成了 json web token = 标题.内容.签名
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
由于生成签名的密码是存在服务器端的,所以就不怕别人篡改JWT,因为别人篡改的JWT 不会被服务器识别。