1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
---
title: HTTP 身份验证
slug: Web/HTTP/Authentication
tags:
- 指南
- 访问控制
- 身份验证
translation_of: Web/HTTP/Authentication
---
<div>{{HTTPSidebar}}</div>
<p class="summary">HTTP 提供一个用于权限控制和认证的通用框架。最常用的HTTP认证方案是HTTP Basic authentication。本页介绍了通用的HTTP认证框架以及展示如何通过HTTP Basic authentication来限制权限访问您的服务器。</p>
<h2 id="通用的_HTTP_认证框架">通用的 HTTP 认证框架</h2>
<p>{{RFC("7235")}} 定义了一个 HTTP 身份验证框架,服务器可以用来针对客户端的请求发送 {{glossary("challenge")}} (质询信息),客户端则可以用来提供身份验证凭证。质询与应答的工作流程如下:服务器端向客户端返回 {{HTTPStatus("401")}}(Unauthorized,未被授权的) 状态码,并在 {{HTTPHeader("WWW-Authenticate")}} 首部提供如何进行验证的信息,其中至少包含有一种质询方式。之后有意向证明自己身份的客户端可以在新的请求中添加 {{HTTPHeader("Authorization")}} 首部字段进行验证,字段值为身份验证凭证信息。通常客户端会弹出一个密码框让用户填写,然后发送包含有恰当的 <code>Authorization</code> 首部的请求。</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/14689/HTTPAuth.png" style="height: 335px; width: 710px;"></p>
<p>在上图所示的基本身份验证过程中,信息交换须通过 HTTPS(TLS) 连接来保证安全。</p>
<h3 id="代理认证">代理认证</h3>
<p>与上述同样的询问质疑和响应原理使用于代理认证。下面介绍一个中间代理需要认证的例子。资源认证和代理认证可以并存,区别于独立的头信息和响应状态码。代理认证,询问质疑的状态码是 {{HTTPStatus("407")}}(必须提供代理证书),响应头{{HTTPHeader("Proxy-Authenticate")}}至少包含一个可用的质制,并且请求头{{HTTPHeader("Proxy-Authorization")}}用作提供证书给代理服务器。</p>
<h3 id="访问拒绝">访问拒绝</h3>
<p>当(代理)服务器收到一个合法认证信息时,若该认证不能获取请求资源的权限,(代理)服务器会返回{{HTTPStatus("403")}}响应状态,说明用户证书权限不够,与 {{HTTPStatus("401")}} 未认证和 {{HTTPStatus("407")}} 未代理认证不同。</p>
<h3 id="跨域图片认证">跨域图片认证</h3>
<p>一个被浏览器最近修复了的潜在的安全漏洞是跨域图片的认证。从 <a href="https://developer.mozilla.org/en-US/Firefox/Releases/59">Firefox 59</a> 起,浏览器在加载不同域的图片资源时,将不会再弹出 HTTP 认证对话框({{bug(1423146)}})。如果攻击者可以将任意图片嵌入到第三方页面中,禁止弹出 HTTP 认证对话框可避免用户的身份凭证被窃取。</p>
<h3 id="HTTP_认证的字符编码">HTTP 认证的字符编码</h3>
<p>浏览器使用 <code>utf-8</code> 编码用户名和密码。Firefox 曾使用 <code>ISO-8859-1</code>,但为与其他浏览器保持一致改为 <code>utf-8</code>,也为了避免 {{bug(1419658)}} 中所描述的潜在问题。</p>
<h3 id="WWW-Authenticate_与_Proxy-Authenticate_首部"><code>WWW-Authenticate</code> 与 <code>Proxy-Authenticate</code> 首部</h3>
<p>{{HTTPHeader("WWW-Authenticate")}} 与 {{HTTPHeader("Proxy-Authenticate")}} 响应消息首部指定了为获取资源访问权限而进行身份验证的方法。它们需要明确要进行验证的方案,这样希望进行授权的客户端就知道该如何提供凭证信息。这两个首部的语法形式如下:</p>
<pre class="syntaxbox">WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
</pre>
<p>在这里,<type> 指的是验证的方案(“基本验证方案”是最常见的验证方案,<a href="/en-US/docs/Web/HTTP/Authentication#Basic_authentication_scheme">会在下面进行介绍</a>)。realm 用来描述进行保护的区域,或者指代保护的范围。它可以是类似于 "Access to the staging site" 的消息,这样用户就可以知道他们正在试图访问哪一空间。</p>
<h3 id="Authorization_与_Proxy-Authorization_首部"><code>Authorization</code> 与 <code>Proxy-Authorization</code> 首部</h3>
<p>{{HTTPHeader("Authorization")}} 与 {{HTTPHeader("Proxy-Authorization")}} 请求消息首部包含有用来向(代理)服务器证明用户代理身份的凭证。这里同样需要指明验证的类型,其后跟有凭证信息,该凭证信息可以被编码或者加密,取决于采用的是哪种验证方案。</p>
<pre class="syntaxbox">Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>
</pre>
<h3 id="验证方案">验证方案</h3>
<p>通用 HTTP 身份验证框架可以被多个验证方案使用。不同的验证方案会在安全强度以及在客户端或服务器端软件中可获得的难易程度上有所不同。</p>
<p>最常见的验证方案是“基本验证方案”("Basic"),该方案会在下面进行详细阐述。 IANA 维护了<a class="external external-icon" href="http://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml">一系列的验证方案</a>,除此之外还有其他类型的验证方案由虚拟主机服务提供,例如 Amazon AWS 。常见的验证方案包括:</p>
<ul>
<li><strong>Basic</strong> (查看 {{rfc(7617)}}, base64编码凭证. 详情请参阅下文.),</li>
<li><strong>Bearer</strong> (查看 {{rfc(6750)}}, bearer 令牌通过OAuth 2.0保护资源),</li>
<li><strong>Digest</strong> (查看 {{rfc(7616)}}, 只有 md5 散列 在Firefox中支持, 查看 {{bug(472823)}} 用于SHA加密支持),</li>
<li><strong>HOBA</strong> (查看 {{rfc(7486)}} (草案), <strong>H</strong>TTP <strong>O</strong>rigin-<strong>B</strong>ound 认证, 基于数字签名),</li>
<li><strong>Mutual</strong> (查看 <a href="https://tools.ietf.org/html/draft-ietf-httpauth-mutual-11">draft-ietf-httpauth-mutual</a>),</li>
<li>
<p><strong>AWS4-HMAC-SHA256</strong> (查看 <a href="http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html">AWS docs</a>).</p>
</li>
</ul>
<h2 id="基本验证方案">基本验证方案</h2>
<p>"Basic" HTTP 验证方案是在 {{rfc(7617)}}中规定的,在该方案中,使用用户的 ID/密码作为凭证信息,并且使用 base64 算法进行编码。</p>
<h3 id="基本验证方案的安全性">基本验证方案的安全性</h3>
<p>由于用户 ID 与密码是是以明文的形式在网络中进行传输的(尽管采用了 base64 编码,但是 base64 算法是可逆的),所以基本验证方案并不安全。基本验证方案应与 HTTPS / TLS 协议搭配使用。假如没有这些安全方面的增强,那么基本验证方案不应该被来用保护敏感或者极具价值的信息。</p>
<h3 id="使用Apache限制访问和基本身份验证">使用Apache限制访问和基本身份验证</h3>
<p>要对Apache服务器上的目录进行密码保护, 你需要一个 <code>.htaccess</code> 和 a <code>.htpasswd</code> 文件.</p>
<p>该 <code>.htaccess</code> 文件格式通常看起来像这样:</p>
<pre>AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user</pre>
<p>该 <code>.htaccess</code> 文件引用一个 <code>.htpasswd</code> 文件,其中每行用冒号(“:”)分隔的用户名和密码. 你不能看到真实的密码因为它们是 <a href="https://httpd.apache.org/docs/2.4/misc/password_encryptions.html">encrypted</a> (在这个例子中是使用了 MD5). 你可以命名<code>.htpasswd</code> 文件 为你所喜欢的名字, 但是应该保证这个文件不被其他人访问. (Apache通常配置阻止访问 <code>.ht*</code> 类的文件).</p>
<pre>aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/
</pre>
<h3 id="nginx访问限制和基本认证">nginx访问限制和基本认证</h3>
<p>在nginx配置中,对需要保护的location你需要做如下配置:<code>auth_basic指令提供密码保护域的名称;auth_basic_user_file指令指定包含用户密文的证书的文件(与apache例子中一致)</code></p>
<p>在 nginx 中, 你需要指定一个保护区域和该 <code>auth_basic</code> 指令提供的保护区域名字. 然后该 <code>auth_basic_user_file</code> 指令指向一个<code>.htpasswd</code> 包含加密用户凭据的文件, 就像上面的 apache 例子.</p>
<pre>location /status {
auth_basic "Access to the staging site";
auth_basic_user_file /etc/apache2/.htpasswd;
}</pre>
<h3 id="使用_URL_中的身份凭证进行的访问(已废弃)">使用 URL 中的身份凭证进行的访问(<s>已废弃</s>)</h3>
<p>许多客户端同时支持避免弹出登录框,而是使用包含用户名和密码的经过编码的 URL,如下所示:</p>
<pre class="example-bad">https://username:password@www.example.com/</pre>
<p><strong>这种 URL 是不赞成使用的。</strong>在 Chrome 中, URL 中的 username:password@ 部分甚至会因为安全原因而被移除。Firefox 则会检查该站点是否真的需要身份验证,假如不是,则会弹出一个警告窗口:你即将使用用户名 “username” 登录 ”www.example.com“ 站点,但是该站点不需要进行身份验证。这可能是在试图进行欺诈。</p>
<h2 id="相关内容">相关内容</h2>
<ul>
<li>{{HTTPHeader("WWW-Authenticate")}}</li>
<li>{{HTTPHeader("Authorization")}}</li>
<li>{{HTTPHeader("Proxy-Authorization")}}</li>
<li>{{HTTPHeader("Proxy-Authenticate")}}</li>
<li>{{HTTPStatus("401")}}, {{HTTPStatus("403")}}, {{HTTPStatus("407")}}</li>
</ul>
|