一些 Web 页面只想让特定的、拥有特定标示的人浏览,为了达到这个目标,必不可少的就是认证功能。生活中常见的认证方式包括:账号密码验证、动态令牌、指纹识别、人脸识别、身份证验证等等。那么,HTTP 常用的认证方式是什么呢?
HTTP 用户身份认证
BASIC 认证
BASIC 认证(基本认证)是从 HTTP/1.0 就定义的认证方式。即便是现在仍有一部分的网站会使用这种认证方式。是 Web 服务器与通信客户端之间进行的认证方式。
- 客户端发出认证请求;
- 服务端接收到请求需要 BASIC 认证,会随 401 状态码 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段包含认证的方式(BASIC)及 Request-URI 安全域字符串(realm);
- 客户端接收到服务端的请求后,对用户名和密码进行 Base64 编码处理,发送给服务器;
- 服务端接收到客户端的请求,对认证信息的正确性进行验证,验证通过后,返回一条包含 Request-URI 资源的响应。
需要注意的是,Base64 编码并非加密处理,因此,BASIC 认证实际是明文传输。
DIGEST 认证
- 客户端发出认证请求;
- 服务器随着状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段内包含认证所需的临时质询码(随机数,nonce)。
- 客户端接收到包含 DIGEST 认证必须的首部 Authorization 信息。首部字段 Authorization 内必须包含 username、realm、nonce、uri 和 response 的字段信息。其中,realm 和 nonce 就是之前从服务器接收到的响应中的字段。
- 服务器确认认证信息的正确性,认证通过后则返回包含 Request-URI 资源的响应。并且会在首部字段 Authentication-Info 中写入一些认证成功的相关信息。
DIGEST 认证提供了高于 BASIC 认证的安全等级,但是和 HTTPS 的客户端认证相比仍旧很弱。DIGEST 认证提供防止密码被窃听的保护机制,但并不存在防止用户伪装的保护机制。
SSL 客户端认证
SSL客户端认证是借由 HTTPS 的客户端证书完成认证的方式。凭借客户端证书认证,服务器可确认访问是否来自合法的客户端。SSL 客户端认证需要事先将客户端证书分发给客户端,且客户端必须安装此证书。
- 客户端发出认证请求;
- 服务端接收到需要认证资源的请求,服务器会发送 Certificate Request 报文,要求客户端提供客户端证书。
- 用户选择将发送的客户端证书后,客户端将客户端证书信息以 Client Certificate 报文方式发送给服务器。
- 服务器验证客户端证书,验证通过后接受证书内客户端的公开密钥,开始 HTTPS 加密通信。
SSL 客户端认证采用双因素认证,认证过程中不仅需要密码这一个因素,还需要申请认证者提供其他持有信息,从而作为另一个因素,与其组合使用的认证方式。通过双因素认证后,就可以确认是用户本人正在使用匹配正确的计算机访问服务器。
使用 SSL客户端认证需要用到客户端证书。而客户端证书需要支付一定费用才能使用。每个认证机构颁发客户端证书的费用不尽相同,平摊到一张证书上,一年费用约几万至十几万日元。服务器运营者也可以自己搭建认证机构,但要维持安全运行就会产生相应的费用。
基于表单认证
基于表单的认证方法并不是在 HTTP 协议中定义的。客户端会向服务器上的 Web 应用程序发送登录信息(Credential),服务器根据登录信息进行认证。
由于使用上的便利性及安全性问题,HTTP 协议标准提供的 BASIC 认证和 DIGEST 认证几乎不怎么使用。另外,SSL客户端认证虽然具有高度的安全等级,但因为导入及维持费用等问题,还尚未普及。
不具备共同标准规范的表单认证,在每个 Web 网站上都会有各不相同的实现方式。如果是全面考虑过安全性能而实现的表单认证,那么就能够具备高度的安全等级。但在表单认证的实现中存在问题的 Web 网站也是屡见不鲜。
基于表单认证一般会使用 Cookie 来管理 Session(会话):
- 客户端把用户 ID 和密码等登录信息放入报文的实体部分, 通常是以 POST 方法把请求发送给服务器。而这时,会使用 HTTPS 通信来进行 HTML 表单画面的显示和用户输入数据的发送。
- 服务器返回用以识别用户的 Session ID。通过验证客户端发送过来的登录信息,进行身份认证,然后把用户的认证状态与 Session ID 绑定后记录在服务器端。
- 客户端接收到从服务器端发来的 Session ID 后,会将其作为 Cookie 保存在本地。下次向服务器发送请求时,浏览器会自动发送 Cookie,所以 Session ID 也随之发送到服务器。服务器端可通过验证接收到的 Session ID 识别用户和其认证状态。
除了以上介绍的应用实例,还有应用其他不同方法的案例。另外,不仅基于表单认证的登录信息及认证过程都无标准化的方法, 服务器端应如何保存用户提交的密码等登录信息等也没有标准化。通常,一种安全的保存方法是,先利用给密码加盐(salt)的方式增加额外信息,再使用散列(hash)函数计算出散列值后保存。但是我们也经常看到直接保存明文密码的做法,这样的做法有密码泄露的风险。
salt 其实就是由服务器随机生成的一个字符串,但是要保证长度足够长,并且是真正随机生成的。然后把它和密码字符串相连接(前后都可以)生成散列值。当两个用户使用了同一个密码时,由于随机生成的 salt 值不同,对应的散列值也将是不同的。这样一来,很大程度上减少了密码特征,攻击者也就很难利用自己手中的密码特征库进行破解。
最后
我的个人主页 里也同步进行了更新,欢迎来逛逛。