HTTP - Authentication
HTTP 提供了一套访问控制和认证的通用框架。最常用的 HTTP 认证方案是 HTTP Basic Authentication。
HTTP 常规的认证流程
HTTP 通用的认证模型非常简单,就是质询/响应 (challenge/response) 框架。以 HTTP Basic Authentication 为例:
- 当客户端请求一个需要认证的资源时,服务器返回一条 401 (Unauthorized) 响应。并在
WWW-Authenticate
响应首部携带如何进行验证的相关信息,其中至少包含一种质询方式。 - 然后,客户端根据
WWW-Authentication
提供的认证要求,在请求中添加Authorization
首部字段进行认证,值为相应认证方案的认证凭证 (如 Basic 认证方案:Basic + “用户名:密码”的 base64 编码)。 - 服务器验证通过,则返回正常的请求。如果认证错误,则返回 403 (Forbidden)。
代理认证 (Proxy Authentication)
服务器可以委托代理服务器提供内部资源的统一访问控制,即代理认证。
如果使用了 HTTP 代理服务器,客户端的访问的其实是代理服务器,请求先经过代理服务器,然后代理服务器根据请求的内容处理请求 (如,过滤掉请求或将请求转发到不同的服务器等等)。如果你的网站是发布到公网上的话,你的代理服务器就暴露在公网上了。如果你的代理服务器没有设置任何访问权限,就可能会被网上的大量代理扫描程序扫描出来,公布到各大免费代理站点。所以,代理服务器最好设置账号密码,而且不要是弱密码。
代理认证与 Basic 认证的过程类似,同样的基于 HTTP 质询/响应框架。
Basic Authentication | Proxy Authentication |
---|---|
401 | 407 |
WWW-Authenticate | Proxy-Authenticate |
Authorization | Proxy-Authorization |
WWW-Authenticate 与 Proxy-Authenticate
WWW-Authenticate
与Proxy-Authenticate
响应头部指定了获取资源访问权限的身份验证方法。1
2WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
<type>
:指验证的类型,如 Basic, Bearer, Digest, HOBA, Mutual等。<realm>
:保护区域的描述,或指定保护的范围。如果未指定realm
,通常客户端显示一个格式化的主机名来代替。
Authorization 与 Proxy-Authorization
Authorization
与Proxy-Authorization
请求消息首部,包含用来向 (代理) 服务器验证身份的凭证。同样需要指明验证的类型,其后跟着验证信息。验证信息可以被编码或者加密,取决于采用的是哪种验证类型。1
2Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>
Nginx 搭建 HTTP Basic Authentication
Nginx ngx_http_auth_basic_module
可以实现 HTTP Basic Authentication 协议。1
2
3
4location / {
auth_basic 'authentication';
auth_basic_user_file conf.d/htpasswd;
}
auth_basic: string | off,默认
off
,不开启。开启 HTTP Basic Authentication 只需要填写一个字符串,该字符串会作为realm
的值,在服务器质询客户端的返回头部信息WWW-Authenticate
中显示,如:WWW-Authenticate: Basic realm="Authorication"
。auth_basic_user_file: 指定访问的用户名和密码的配置文件,可以是相对路径或绝对路径的文件。当使用相对路径时,则相对 nginx 安装配置目录,如
/etc/nginx/
或/etc/nginx/conf.d/
试了下都可以。文件配置内容格式,如htpasswd
:1
2
3# comment
name1:password1
name2:password2:comment- 可以用
#
注释 - 可以设置多个用户名和密码,每行一个,用户名和密码之间用
:
隔开,注释也可以写在密码后面,用:
隔开。 - 用户名直接填写,但是密码需要经过加密。如,Linux 系统,密码
123456
可以用openssl passwd 123456
生成。
- 可以用
假设,刚刚搭建的服务器地址为:127.0.0.1。从浏览器访问 http://127.0.0.1
就会收到一个 401 质询,弹出一个用户名和密码的输入框。用户输入账号和密码之后,浏览器会用 :
将其连接起来,编成 base64 编码,然后将其放在请求头部的 Authorization 中发送给服务端。服务端验证通过后就可以正常浏览页面的内容了。
HTTP 基础认证过程
假如,nginx 配置好的认证页面为 http://127.0.0.1
telnet 建立一条 http 连接
1
telnet 127.0.0.1 80
发送正常的请求,会返回 401
1
2
3
4
5
6
7
8
9
10HEAD / HTTP/1.1
Host: 172.16.105.114
HTTP/1.1 401 Unauthorized
Server: BDSCAN/1.5.0
Date: Wed, 17 Jan 2018 08:26:04 GMT
Content-Type: text/html
Content-Length: 195
Connection: keep-alive
WWW-Authenticate: Basic realm="authentication"发送带验证信息的请求
1
2
3
4
5
6
7
8
9
10
11
12
13HEAD / HTTP/1.1
Host: 172.16.105.114
Authorization: Basic bGl6czoxMjM0NTY=
HTTP/1.1 200 OK
Server: BDSCAN/1.5.0
Date: Wed, 17 Jan 2018 08:26:59 GMT
Content-Type: text/html
Content-Length: 334
Last-Modified: Tue, 16 Jan 2018 08:55:10 GMT
Connection: keep-alive
ETag: "5a5dbdee-14e"
Accept-Ranges: bytes
验证信息放在请求头的 Authorization
,即 Authorization: Basic base64-username-and-password
。base64-username-and-password
为用户名和密码用 :
连接起来,并经过 base64 编码等到的字符串 (即上面的 bGl6czoxMjM0NTY=
) 。Python(python2) 生成:1
2
3
4
5import base64
username = 'lizs'
password = '123456'
msg = base64.b64encode('%s:%s' % (username, password))