微服务中鉴权方式OAtuh2与JWT的比较

统一认证与授权是微服务架构的基础功能,微服务架构不同于单体应用的架构,认证和授权非常集中。当服务拆分之后,对各个微服务认证与授权变得非常分散,所以在微服务架构中,将集成统一认证与授权的功能,作为横切关注点。

常见的认证与授权方案

常见的认证与授权方案有 OAuth、分布式 Session、OpenID 和 JWT 等

OAtuh2

相关理论的介绍主要来自于OAuth2官方文档,相关地址为https://tools.ietf.org/html/rfc6749。

OAuth2是当前授权的行业标准,其重点在于为Web应用程序、桌面应用程序、移动设备以及室内设备的授权流程提供简单的客户端开发方式。它为第三方应用提供对HTTP服务的有限访问,既可以是资源拥有者通过授权允许第三方应用获取HTTP服务,也可以是第三方以自己的名义获取访问权限。

角色

OAuth2 中主要分为了4种角色

  • resource owner 资源所有者,是能够对受保护的资源授予访问权限的实体,可以是一个用户,这时会被称为end-user。
  • resource server 资源服务器,持有受保护的资源,允许持有访问令牌(access token)的请求访问受保护资源。
  • client 客户端,持有资源所有者的授权,代表资源所有者对受保护资源进行访问。
  • authorization server 授权服务器,对资源所有者的授权进行认证,成功后向客户端发送访问令牌。

在很多时候,资源服务器和授权服务器是合二为一的,在授权交互的时候是授权服务器,在请求资源交互是资源服务器。但是授权服务器是单独的实体,它可以发出被多个资源服务器接受的访问令牌。

协议流程

官方流程图

 +--------+                               +---------------+
 |        |--(1)- Authorization Request ->|   Resource    |
 |        |                               |     Owner     |
 |        |<-(2)-- Authorization Grant ---|               |
 |        |                               +---------------+
 |        |
 |        |                               +---------------+
 |        |--(3)-- Authorization Grant -->| Authorization |
 | Client |                               |     Server    |
 |        |<-(4)----- Access Token -------|               |
 |        |                               +---------------+
 |        |
 |        |                               +---------------+
 |        |--(5)----- Access Token ------>|    Resource   |
 |        |                               |     Server    |
 |        |<-(6)--- Protected Resource ---|               |
 +--------+                               +---------------+

流程主要包含以下的6个步骤

  1. 客户端请求资源所有者的授权;
  2. 资源所有者同意授权,返回授权许可(Authorization Grant),这代表了资源所有者的授权凭证;
  3. 客户端携带授权许可要求授权服务器进行认证,请求访问令牌;
  4. 授权服务器对客户端进行身份验证,并认证授权许可,如果有效,返回访问令牌;
  5. 客户端携带访问许可向资源服务器请求受保护资源的访问;
  6. 资源服务器验证访问令牌,如果有效,接受访问请求,返回受保护资源。

客户端授权类型

为了获取访问令牌,客户端必须获取到资源所有者的授权许可。OAuth2默认定了四种授权类型,当然也提供了用于定义额外的授权类型的扩展机制。默认的四种授权类型为:

  1. authorization code 授权码类型
  2. implicit 简化类型(也称为隐式类型)
  3. resource owner password credentials 密码类型
  4. client credential 客户端类型

下面对常用的授权码类型和密码类型进行详细的介绍。

授权码类型

授权码类型(authorization code)通过重定向的方式让资源所有者直接与授权服务器进行交互来进行授权,避免了资源所有者信息泄漏给客户端,是功能最完整、流程最严密的授权类型,但是需要客户端必须能与资源所有者的代理(通常是Web浏览器)进行交互,和可从授权服务器中接受请求(重定向给予授权码),授权流程如下:

 +----------+
 | Resource |
 |   Owner  |
 |          |
 +----------+
      ^
      |
     (2)
 +----|-----+          Client Identifier      +---------------+
 |         -+----(1)-- & Redirection URI ---->|               |
 |  User-   |                                 | Authorization |
 |  Agent  -+----(2)-- User authenticates --->|     Server    |
 |          |                                 |               |
 |         -+----(3)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
  (1)  (3)                                        |      |
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(4)-- Authorization Code ---------'      |
 |  Client |          & Redirection URI                  |
 |         |                                             |
 |         |<---(5)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)
————————————————

1.客户端引导资源所有者的用户代理到授权服务器的endpoint,一般通过重定向的方式。客户端提交的信息应包含客户端标识(client identifier)、请求范围(requested scope)、本地状态(local state)和用于返回授权码的重定向地址(redirection URI);
2.授权服务器认证资源所有者(通过用户代理),并确认资源所有者允许还是拒绝客户端的访问请求;
3.如果资源所有者授予客户端访问权限,授权服务器通过重定向用户代理的方式回调客户端提供的重定向地址,并在重定向地址中添加授权码和客户端先前提供的任何本地状态;
4.客户端携带上一步获得的授权码向授权服务器请求访问令牌。在这一步中授权码和客户端都要被授权服务器进行认证。客户端需要提交用于获取授权码的重定向地址;
5.授权服务器对客户端进行身份验证,和认证授权码,确保接收到的重定向地址与第三步中用于的获取授权码的重定向地址相匹配。如果有效,返回访问令牌,以及可能返回的刷新令牌(Refresh Token)。

密码类型

JWT

JWT(JSON Web Token)作为一个开放的标准,通过紧凑(Compact)或者自包含(Self-contained)的方式,定义了用于在各方之间发送的安全JSON对象。

JWT可以很好地充当在上面介绍的访问令牌和刷新令牌的载体,这是Web双方之间进行安全传输信息的良好方式。只有授权服务器持有签发和验证JWT的密钥,那么就只有授权服务器能验证JWT的有效性以及发送带有签名的JWT,这就唯一保证了以JWT为载体的令牌的有效性和安全性。

它由三部分组成,每部分通过.分隔开,分别是:
Header(头部)
Payload(有效负荷)
Signature(签名)

头部

头部通常由两部分组成:
·typ:类型,一般为JWT。
·alg:加密算法,通常是HMAC SHA256或者RSA。

一个简单的头部例子如下所示:
{
“alg”: “HS256”
“typ”: “JWT”
}
这部分JSON会由Base64Url编码,构成JWT的第一部分,如下所示:
R5cCI6IJ9eyJh2IV7Hy6IkpX5cCIJ9

有效载荷

  1. Registered claims(注册声明)。这是一组预定的声明,但并不强制要求。它提供了一套有用的、能共同使用的声明。主要有iss(JWT签发者)、exp(JWT过期时间)、sub(JWT面向的用户)、aud(接受JWT的一方)等。
  2. Public claims(公开声明)。公开声明中可以添加任何信息,一般是用户信息或者业务扩展信息等。
  3. Private claims(私有声明)。由JWT提供者和消费者共同定义的声明,既不属于注册声明也不属于公开声明。

一般不建议在Payload中添加任何敏感信息,因为Base64是对称解密的,这意味着Payload中的信息是可见的。
一个简单的Payload例子如下所示:

{
"name": "enzo",
"exp": 1568287607,
"userId": "00001"
}

这部分JSON会由Base64Url编码,构成JWT的第二部分:
B29umiY1MTEZy2FuIiMTIzNDU2In0mV4cSeyCI6MTUxODAJuYW1lIIs1NywidXNlcklkIjo

签名

要创建签名,需要编码后的头部、编码后的Payload、一个密钥,最后通过在头部alg键值定义的加密算法加密生成签名,生成签名的伪代码如下所示:

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

上述代码中用到的加密算法为HMACSHA256。密钥保存在服务端用于验证JWT以及签发JWT,所以必须只由服务端持有,不该泄露出去。
一个简单的签名如下所示:
MnK90MjwMpp0acCi9Pk6m07971I2vcc6y7ki2PQcs
这将成为JWT的第三部分。

这三部分通过“.”分割,组成最终的JWT,如下所示:
R5cCI6IJ9eyJh2IV7Hy6IkpX5cCIJ9.B29umiY1MTEZy2FuIiMTIzNDU2In0mV4cSeyCI6MTUxODAJuYW1lIIs1NywidXNlcklkIjo.MnK90MjwMpp0acCi9Pk6m07971I2vcc6y7ki2PQcs

你可能感兴趣的:(微服务,go,jwt,oauth2,微服务,go,权限认证)