一种传递HTTP认证信息的方式

原理:
在HTTP认证(Basic,Digest)中,当浏览器访问受保护的资源时,WEB服务器会返回响应:
HTTP/1.1 401 Authorization Required
并在响应头WWW-Authenticate中指明需要的认证方式。之后浏览器向使用计算机的用户
询问用户名和密码,然后将这些信息加密后通过Authorization和其它请求头发送给服务器
如果用户名密码有效,服务器就返回客户请求的资源。客户的所有后续请求也要提供相同的
用户信息(因为HTTP是无状态的)
如果用户名密码无效,服务器会再次返回401代码,然后浏览器再次询问用户。
IE浏览器在用户输入几次错误密码之后放弃,显示服务器返回的401错误页面,
Firefox允许用户一直重试,直到密码正确,或者用户点击取消,对话框才会消失,然后
显示401错误页面。

我们不难看出,要想在各个应用或者站点之间传递HTTP认证信息,关键是修改浏览器的
请求,添加Authorization及相关请求头。我们也知道,对浏览器进行操作这样的任务,
只能由客户端代码来完成(Javascript,Flash,Java Applet…)。

在Javascript可用的对象中,XMLHttpRequest直接支持HTTP认证,它会将其open方法中
提供的用户名密码处理后放到Authorization请求头,发给服务器。之后浏览器会记住
这一认证信息并在访问相关资源时自动使用。

实现:

情景1:
同一个web服务器上,/auth 下的应用负责进行用户认证,搜集信息等操作 /private 下的资源受到保护
/auth认证后的用户不需要再次输入用户名密码即可访问/private下的资源.

我们可以在/auth 中添加如下逻辑来实现:

if auth fail:
do fail task(eg. show an error page)
else:
#display the following code

<html><head>
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
url:"/private/,
type:"POST",
async:false,
username:"private username",
password:"private password",
success:function(){
document.location = "/private";
}
});
});
</script>
</head>
<body></body>
</html>

这里的逻辑是,当用户认证通过,就返回上面这段代码给浏览器。这段代码(使用jQuery)
首先通过XMLHttpRequest将认证信息发给服务器(以便浏览器记住之后使用).
如果一切无误,再将用户重定向到被保护的资源,这时用户已通过认证了。

情景2:
WEB服务器A上的/autha 对用户进行认证,通过认证的用户可以访问WEB服务器B上的 /private
下的资源.

在这种情况下,由于XMLHttpRequest不能跨站点操作,我们需要在服务器B上建立一个中介,
如上面的/auth,它接受来自/autha的数据(实际上是/autha交给浏览器,浏览器再交给/auth
,如通过query string),进行处理后,得到认证信息,然后通过情景1的方式传递给/private

缺点:使用这种方式,在Javascript代码中直接包含了明文的用户名和密码,这有两个问题:
1.明文传输的用户名和密码容易被窃听
2.这里包含的信息是可以直接访问受保护资源,这样用户得到这些信息之后可以跳过其它认证步骤。

This entry was posted in WEB Application and tagged . Bookmark the permalink.

Leave a Reply