ShiningDan的博客

鉴权认证方案总结

本文是鉴权认证相关知识点的方案总结

  1. Basic Auth
  2. OAuth 2.0
    1. bearer Token && MAC Token
    2. JWT
    3. PKCE:移动应用程序建议使用的扩展
  3. SAML
  4. OpenID
  5. CAS

首先,需要了解的三个英文单词:

  1. accounting:账号,记账:记录用户的操作行为、发生时间
  2. authentication:认证,鉴定:确认访问网络的用户身份,判断访问者是否合法
  3. authorization:授权,批准:对通过认证的用户,授权其可以使用哪些服

Basic Auth(HTTP 基本认证)

每次请求API时都提供用户的 username 和 password,用 base64 处理特殊字符,进行 URL 安全转换

基于 Session 的认证

Session 对应的是认证的流程,authentication

常见的服务端认证方法有基于 Cookie 的认证,如 session;以及 Token (令牌)认证,如 JWT。

OAuth 2.0,基于 Token 的认证和授权

官方网站:OAuth 2.0

首先明确范围,OAuth 2.0 是用来进行授权的,authorization,不过在授权之前还是需要登录,也就是 authentication 的流程。但是 Oauth 主要关心的是授权的流程,如何登录,也可以使用 OpenID 的方式

OAuth 2 是一种授权框架,允许第三方应用通过用户授权的形式访问服务中的用户信息,最常见的场景是授权登录

OAuth2 角色

OAuth 定义了四种角色

  • 资源拥有者 (Resource Owner)
  • 客户端 (Client)
  • 资源服务器 (Resource Server)
  • 授权服务器 (Authorization Server)

假设我们做了一个 SNS,它有一个功能,可以让会员把他们在Google上的联系人导入到SNS上,那么此时的会员是 Resource Owner,Google是 Resource Server 和 Authorization Server,而SNS则是 Client。

OAuth 2 的授权流程

1
2
3
4
5
6
7
8
9
(A)用户访问客户端,后者将前者导向认证服务器。

(B)用户选择是否给予客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。

(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。

(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

具体的参数传递示例,可以查看 理解OAuth 2.0 | 阮一峰的网络日志

Client 应用注册

在应用 OAuth 2 之前,你必须在授权方(Resource Server)服务中注册你的应用。诸如此类 OAuth 实现平台中一般都要求开发者提供如下所示的授权设置项。

  • 应用名称
  • 应用网站
  • 重定向URI或回调URL

一旦你的应用注册成功,授权方服务将以 client id 和 client secret 的形式为应用发布 client credentials(客户端凭证)。

client id 是公开透明的字符串,授权方服务使用该字符串来标识应用程序。

当应用请求访问用户的帐户时,client secret用于验证应用身份,并且必须在客户端和服务之间保持私有性。

客户端的授权模式

客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。

理解OAuth 2.0 | 阮一峰的网络日志

  • 授权码模式(authorization code):功能最完整、流程最严密的授权模式,通过客户端的后台服务器,与”服务提供商”的认证服务器进行互动。
  • 简化模式(implicit):不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名。
  • 密码模式(resource owner password credentials):用户向客户端提供自己的用户名和密码。客户端使用这些信息,向”服务商提供商”索要授权。
  • 客户端模式(client credentials):客户端以自己的名义要求”服务提供商”提供服务,其实不存在授权问题。

对于token的描述,OAuth2.0协议只是一笔带过的说它是一个字符串,用于表示特定的权限、生命周期等,但是却没有明确阐述token的生成策略,以及如何去验证一个token。一般 access token 有以下两种方式:Bearer Token 和 MAC Token。

这两种 Token 使用的示例:OAuth2.0协议原理与实现:TOKEN生成算法

Bearer Token

BEARER类型token是建立在HTTP/1.1版本之上的token类型,需要TLS(Transport Layer Security)提供安全支持,该协议主要规定了BEARER类型token的客户端请求和服务端验证的具体细节。

MAC Token

会有站点继续在使用HTTP,在这类站点中BEARER类型的token存在安全隐患,这个时候MAC类型的token正是用武之地,MAC类型的token设计的主要目的就是为了应对不可靠的网络环境。

MAC类型相对于BEARER类型对于用户资源请求的区别在于,BEARER类型只需要携带授权服务器下发的token即可,而对于MAC类型来说,除了携带授权服务器下发的token,客户端还要携带时间戳,nonce,以及在客户端计算得到的mac值等信息,并通过这些额外的信息来保证传输的可靠性。

JWT

JWT 是 Token 的一种

JWT 是用来进行用户认证的,即:authentication。

在 OAuth 2.0 中,当客户端 Client 通过 code 换得一个 access-token。之后 clinet 每一次去访问资源服务器 (Resource Server) 的时候,就需要带上 access-token,这个 access-token 就可以使用 JWT 进行生成。

生成 JWT:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Header
{
"alg": "HS256",
"typ": "JWT"
}

// Payload
{
// reserved claims
"iss": "a.com",
"exp": "1d",
// public claims
"http://a.com": true,
// private claims
"company": "A",
"awesome": true
}

// $Signature
HS256(Base64(Header) + "." + Base64(Payload), secretKey)

// JWT
JWT = Base64(Header) + "." + Base64(Payload) + "." + $Signature

验证 JWT:

服务端接收到 token 之后,会逆向构造过程,decode 出 JWT 的三个部分,这一步可以得到 sign 的算法及 payload,结合服务端配置的 secretKey,可以再次进行 $Signature 的生成得到新的 $Signature,与原有的 $Signature 比对以验证 token 是否有效,完成用户身份的认证,验证通过才会使用 payload 的数据。

服务端最终只是为了验证 $Signature 是否仍是自己当时下发给 client 的那个,用户信息通过 base64 反解码就可以得到,所以不要在 payload 里面加上用户密码等敏感信息。JWT 的目的不是为了隐藏或者保密数据,而是为了确保数据确实来自被授权的人创建的(不被篡改)

应用场景

Server 端生成 JWT

  1. 浏览器将用户名和密码以post请求的方式发送给服务器。
  2. 服务器接受后验证通过,用一个密钥生成一个JWT。
  3. 服务器将这个生成的JWT返回给浏览器。
  4. 浏览器将JWT包含在authorization header里面,然后发送请求给服务器。
  5. 服务器可以在JWT中提取用户相关信息。进行验证。
  6. 服务器验证完成后,发送响应结果给浏览器。

Client 端生成 JWT

Google 的一些 API 诸如 Prediction API 或者 Google Cloud Storage,是不需要访问用户的个人数据的,因而不需要经过用户的授权这一步骤,应用程序可以直接访问。

  1. 首先你需要再 Google API 上创建一个服务账号(service account)
  2. 获取服务账号的认证信息(credential),包括邮箱地址,client ID,以及一对公钥/私钥
  3. 使用 client ID 和私钥创一个签名的 JWT,然后将这个 JWT 发送给 Google 交换 access token
  4. Google 返回 access token
  5. 程序通过 access token 访问 API

PKCE:Proof Key for Code Exchange, better security for native apps

OAuth 2.0 的推荐流程中,Client 获得 Code 去换取 access-token 的时候,是通过后端进行的,并且要换的时候还需要 client_id 和 client_secret。如果是终端,没有后端的帮助下,可以使用 PKCE 这种方式来进行登录以及授权。PKCE 的方式,不需要 client_secret 就可以完成全流程。

要使用 PKCE,后端必须进行特殊的配置。

SAML

The Difference Between SAML 2.0 and OAuth 2.0

全面了解Token,JWT,OAuth,SAML,SSO

SAML Workflow:

相比于 OAuth workflow:

我们可以看到,SAML 的流程相比于 OAuth 的流程在于, Service Provider 在 SAML 流程中,不用再根据 Token 去请求用户信息。用户的信息在 SAML Token 中就已经被签名,然后传输过来。

从 Idp 跳转到 Service Provider 有两种方法:

  1. 第一种是 HTTP Redirect,这种方法可能遇到一个问题,就是用户的信息会在 URL 中传递给 Service Provider,如果用户信息比较多,URL 的长度就可能超过最大长度,就会导致收到的用户信息不全。
  2. 第二种是使用 HTTP POST 进行跳转,附带上用户的信息,但是使用这种方法在移动端的支持不好

为了实现比较好的获取用户信息的流程,OAuth 的方案是,Service Provider 会去在用户访问的时候,使用 Access-Token 换用户信息。

还有一个原因,因为这个 token 有可能被黑客截获,如果黑客截获了这个token,那用户的资源也就暴露在这个黑客之下了。

OpenID

openID 希望帮用户提供一个身份ID,可以在多个网站用来登录。

可以理解为 Oauth 的前置流程,跳转到其他的登录系统进行登录。但是登录之后,不会返回 code 码,而是告诉说这个账户是否是合法账户,该站点无权访问你的在被登录系统上的数据

所以,OpenID 只用于身份认证(Authentication)。

  1. 用户希望访问其在http://example.com的账户
  2. http://example.com (在OpenID的黑话里面被称为“Relying Party”) 提示用户输入他/她/它的OpenID
  3. 用户给出了他的OpenID,比如说”http://user.myopenid.com”
  4. http://example.com 跳转到了用户的OpenID提供商“mypopenid.com”
  5. 用户在”myopenid.com”(OpenID provider)提示的界面上输入用户名密码登录
  6. “myopenid.com” (OpenID provider) 问用户是否要登录到http://example.com
  7. 用户同意后,”myopenid.com” (OpenID provider) 跳转回http://example.com

鉴权流程

  1. 终端用户请求登录RP网站,用户选择了以OpenID方式来登录
  2. RP将OpenId的登录界面返回给终端用户
  3. 终端用户以OpenID登陆RP网站
  4. RP网站对用户的OpenID进行标准化,此过程非常负责。由于OpenID可能是URI,也可能是XRI,所以标准化方式各不相同。具体标准化过程是:如果OpenID以xri://、xri://$ip或者xri://$dns开头,先去掉这些符号;然后对如下的字符串进行判断,如果第一个字符是=、@、+、$、!,则视为标准的XRI,否则视为HTTP URL(若没有http,为其增加http://)。
  5. RP发现OP,如果OpenId是XRI,就采用XRI解析,如果是URL,则用Yadis协议解析,若Yadis解析失败,则用Http发现。
  6. RP跟OP建立一个关联。两者之间可以建立一个安全通道,用于传输信息并降低交互次数。
  7. OP处理RP的关联请求
  8. RP请求OP对用户身份进行鉴权
  9. OP对用户鉴权,请求用户进行登录认证
  10. 用户登录OP
  11. OP将鉴权结果返回给RP
  12. RP对OP的结果进行分析

CAS

CAS Protocol

SSO 仅仅是一种架构,一种设计,而 CAS 则是实现 SSO 的一种手段。两者是抽象与具体的关系。当然,除了 CAS 之外,实现 SSO 还有其他手段,比如简单的 cookie。

OAuth,SAML,OpenId,OpenId Connect 都可以作为 CAS 的实现方案

HTTPS/SSL

HTTPS 的作用

  • 内容加密 建立一个信息安全通道,来保证数据传输的安全;
  • 身份认证 确认网站的真实性
  • 数据完整性 防止内容被第三方冒充或者篡改

简介

访问一个网站,不是直接到网站的,需要中间有很多的服务器路由器的转发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
traceroute www.baidu.com
traceroute: Warning: www.baidu.com has multiple addresses; using 61.135.169.125
traceroute to www.a.shifen.com (61.135.169.125), 64 hops max, 52 byte packets
1 * 192.168.1.1 (192.168.1.1) 204.744 ms 11.478 ms
2 111.196.8.1 (111.196.8.1) 14.976 ms 2.857 ms 3.399 ms
3 114.244.94.209 (114.244.94.209) 3.753 ms 12.121 ms 6.658 ms
4 124.65.59.29 (124.65.59.29) 6.509 ms
123.126.9.85 (123.126.9.85) 4.823 ms
125.33.187.153 (125.33.187.153) 11.348 ms
5 202.106.37.46 (202.106.37.46) 4.595 ms
61.51.117.6 (61.51.117.6) 12.987 ms
124.65.59.214 (124.65.59.214) 6.392 ms
6 123.125.248.46 (123.125.248.46) 4.384 ms
123.125.248.42 (123.125.248.42) 5.135 ms
123.125.248.98 (123.125.248.98) 6.298 ms
7 * * *
8 * * *

这些个节点,任何一个都可以串改你的信息和发给你的信息。所以需要对传输的内容进行加密,防止中间节点注入、或替换内容

所以为了安全起见,建议使用 https。

协议

  • HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):可以理解为HTTP+SSL/TLS, 即 HTTP 下加入 SSL 层。应用层生成的内容,加密后,才交给传输层
  • SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间。
  • TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)。1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2

加密解密

  1. 首先客户端通过URL访问服务器建立SSL连接。
  2. 服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。
  3. 客户端验证证书,开始协商SSL连接的安全等级,也就是信息加密的等级。
  4. 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话堆成加密密钥进行加密,并传送给网站。
  5. 服务器利用自己的私钥解密出会话对称加密密钥。(只有私钥能解开)
  6. 服务器利用会话对称加密密钥加密与客户端之间的通信。

对称加密

优点:加密解密速度快

缺点:

  1. 不同的客户端、服务器数量庞大,所以双方都需要维护大量的密钥,维护成本很高
  2. 因每个客户端、服务器的安全级别不同,密钥极易泄露

非对称加密

使用场景:

  1. 公钥加密后只能该用户的私钥才能解密。这种情况下,公钥是用来加密信息的,确保只有特定的人(用谁的公钥就是谁)才能解密该信息。
  2. 公钥是用来解密信息的,确保让别人知道这条信息是真的由我发布的,是完整正确的。接收者由此可知这条信息确实来自于拥有私钥的某人,这被称作数字签名,公钥的形式就是数字证书。谁要证明自己的身份,谁就有私钥(比如给 Github 配置 SSH Key,就是把公钥证书给 Github,然后用户用私钥证明自己的身份)

私钥加密的消息

缺点:

  1. 加密解密速度慢
  2. 公钥是公开的(也就是黑客也会有公钥),所以私钥加密的信息,如果被黑客截获,其可以使用公钥进行解密,获取其中的内容

优点:

  1. 服务端维护一个私钥,成本小

获得公钥

遇到的问题:

  1. 客户端如何获得公钥
  2. 如何确认服务器是真实的而不是黑客

这里就会用到 SSL 证书:

客户端如何获得公钥:在第 2 步,服务端收到客户端请求后,会将网站支持的证书信息传送一份给客户端,证书中包含公钥。

证书:

  1. 证书的发布机构CA
  2. 证书的有效期
  3. 公钥
  4. 证书所有者
  5. 签名

客户验证证书:

  1. 首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验
  2. 浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发
  3. 如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的。
  4. 如果找到,那么浏览器就会从操作系统中取出 颁发者CA 的公钥,然后对服务器发来的证书里面的签名进行解密
  5. 浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比
  6. 对比结果一致,则证明服务器发来的证书合法,没有被冒充
  7. 此时浏览器就可以读取证书中的公钥,用于后续加密了

ATS

苹果(Apple)公司一向有着对安全性要求极高的著称,如果你申请了SSL证书并且部署到服务器中,但这并不意味SSL部署符合Apple ATS的检测要求,Apple对证书算法、有效期、加密套件、SSL安全漏洞都有极严格的要求。

  1. 允许自签(本地计算机信任),或者受信任的 CA
  2. TLS 至少 1.2
  3. 对称加密算法要求
  4. Key 的长度要求
  5. 签发证书的通用名称证书与域名匹配

详细

Requirements for Connecting Using ATS
With App Transport Security (ATS) fully enabled, the system requires that your app’s HTTP connections use HTTPS and that they satisfy the following security requirements:

  1. The X.509 digital server certificate must meet at least one of the following trust requirements:

    1. Issued by a certificate authority (CA) whose root certificate is incorporated into the operating system

    2. Issued by a trusted root CA and installed by the user or a system administrator

  2. The negotiated Transport Layer Security (TLS) version must be TLS 1.2. Attempts to connect without TLS/SSL protection, or with an older version of TLS/SSL, are denied by default.
  3. The connection must use either the AES-128 or AES-256 symmetric cipher. The negotiated TLS connection cipher suite must support perfect forward secrecy (PFS) through Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) key exchange, and must be one of the following:
    1. TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    2. TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    3. TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  4. The leaf server certificate must be signed with one of the following types of keys:
    Rivest-Shamir-Adleman (RSA) key with a length of at least 2048 bits
    Elliptic-Curve Cryptography (ECC) key with a size of at least 256 bits

如何自签

参考