什么是Web认证
简而言之,web认证就是一个确认对方身份的过程。Web认证最典型的方式是通过用户名和密码。
Web认证有多种方式
A. Http协议内建的认证方法
1. Http Basic Authentication (Http基本认证)
HTTP基本认证是最简单也是曾经使用过很长时间的一种认证方式。基本认证要求为每一个保护域(realm)提供一个用户名和密码进行认证。
流程简介:
a. 客户端浏览器访问一个受http基本认证保护的资源。
b. 服务器返回401(authentication required)状态,要求客户端提供用户名和密码进行认证。Response Header里面有一个属性WWW-Authenticate,它的值比如: Basic realm="Restlet tutorial"。
c. 客户端弹出一个窗口,用于输入用户名和密码(基本上所有的浏览器都提供对基本认证的支持,它们都内建了一个用户名密码输入窗口)。
d. 输入用户名密码并确认之后,客户端把%username%:%password%用Base64进行编码后通过Request Header: Authorization传送给服务器,所以可以看到Http基本认证是明文传输,安全风险很大。比如Authorization: Basic xxxxxxxxxx.
e. 如果认证成功,则返回相应的资源。如果认证失败,则跳回b,重新进行认证。
特点:
*. Http是无状态的,即使来自同一个客户端,对同一个realm内资源的每一个访问还是会被要求进行认证。
*. 客户端会缓存用户名和密码,并和认证域(authentication realm)一起保存。所以,如果对同一个域(realm)的其它资源进行访问,不需要你重新输入用户名和密码。
*. 登录信息会和认证域以及服务器名一起存储,所以可以很好地和其他登录信息区分开来。
*. 基本认证方式是不安全的,因为用户名密码以及内容都是以非加密的方式传输。
2. Digest Authentication (摘要式身份认证)
摘要式认证是一种基于challenge-response的认证模式。
流程简介:
a. 客户端发起一个请求(没有认证信息)。
b. Web服务器返回一个带有WWW-Authenticate头的response(401),请求提供认证。
c. 客户端返回用户名和密码的摘要信息(比如说MD5加密),而不是明文。
d. 通过认证,则返回相应的内容。否则,继续b。
特点:
*. 摘要认证主要是为了解决基本认证中最大的漏洞,即用明文传输用户名和密码的问题。
*. 挑战模式:每次返回401响应的时候,都会返回一个nonce(number used only once)。或者,为了安全起见,还可能会使用一次性nounce(每个request都得到一个不同的nounce)等其它方法来加强安全性。
*. Checksum(默认是MD5 checksum)是username, password, nonce值, HTTP方法, 和被请求的URI的checksum。
*. 安全隐患:虽然密码并非明文传输,但黑客还是可以利用digest值来访问网站。并且,它对内容并不加密。
B. Form-based
基于Form的认证方式是高度可定制,也应该是目前用地最多的一种认证方式。
流程简介:
1. 客户端通过一个form,把用户名和密码post给服务端。
2. 服务端通过一些逻辑来判断认证是否有效。
3. 如果认证成功,服务器返回一个cookie(一个能唯一确认客户端的cookie,比如sessionId),用于客户端接下来的访问。如果认证失败,会提示用户进行重新输入用户名密码再次认证。
特点:
*. 高度可定制:可以根据自己的需要来实现认证逻辑。
*. 服务器端要有一个保存客户端信息的地方,比如session。
*. 客户端要有一个cookie来表明自己的身份,一般是username和一个cookie值(比如sessionId)的组合。
*. 客户端cookie的生命周期和安全性息息相关。比如现在很多站点都支持“remember me”,其实就是在服务器端remember session并在客户端remember cookie。有些站点为了更好的安全性,用这种方式登录时,如果要执行一些重要的操作比如改密码,会要求客户用用户名和密码的方式重新登录。
C. 证书认证
证书认证方式比之其他方式是最安全的认证方式。
对于数字证书的作用,我在这篇文章 里面做了详细介绍。
D. 微软提供的认证方式
这几种认证方式都是微软提供的,不做太多介绍。
1. NTLM,IE only。
2. Microsoft Passport(Single Signon).
现在很多网站都有记住登录状态 的功能。比如gmail,豆瓣等。
现在让我们通过豆瓣来看看如何实现remember me 。
下图为豆瓣的登录页面 :
1. 不选择“记住我”
我们可以得到login页面的response header里的Set-cookie值为。
ue="xxxxx@gmail.com"; domain=.douban.com; expires=Thu, 01-Jan-2012 00:00:00 GMT
dbcl2="1123439:yhsdfd1yvQ"; path=/; domain=.douban.com
其中的ue是用户名,dbcl2为类似于sessionId的用户identification。
可以看出,这是标准的form-based认证方式。
2. 选择“记住我”
得到的response为:
ue="xxxxxx@gmail.com"; domain=.douban.com; expires=Thu, 01-Jan-2012 00:00:00 GMT
dbcl2="1123439:vY9ssdff0"; path=/; domain=.douban.com; expires=Wed, 25 Mar 2009 07:29:59 GMT
跟前者的唯一区别是在dbcl2后加了一个过期期限值,刚好是一个月。
我们已经可以看出,其实本质上,就是在服务器端记住session,并且在客户端记住cookie一个月。在一个月内,都使用相同的cookie去访问服务端。
验证一下,重新访问,果然使用的是同一个cbdl2值。
问题
显而易见,这里最大的问题在于安全问题。
假如cookie被盗,则黑客可以使用这个dbcl2值登录。
那怎么解决呢?很多站点会对用此种方式登录的用户行为进行限制,他们只能执行一般如查看信息等操作,而不能执行如修改密码等安全级别较高的操作。如果用户要修改密码,将被要求重新登录。
当然,现在很多站点在修改密码时都需要输入旧密码,相当于做了一层类似的保护。