/ 闭门造轮子 / HTTP状态码401

HTTP状态码401

2012-11-07 posted in [问题即经验]

开始设计RESTful的HTTP请求时想用401这个状态来做登录验证的过滤器。即如果请求一个资源需要登陆,那么由浏览器的登录框弹出提示,输入用户密码登陆后原请求继续。然后搜到这个Gist:1686663,参照例子写了个demo测试,情况各种诡异,发现401请求验证这方式还真是个坑啊。

然后Google之,查到一个问题:HTTP authentication logout via PHP,大意是说HTTP协议已经明确定义认证是永久性的,除非再次发送一个401给客户端,让他进行错误认证或者直接关闭,否则浏览器没有责任清除已认证的证书信息。有人说用Ajax的方式再发一个无认证header的请求来完成,但没有测试过。

另一个人也问:http basic authentication “log out”,后面有人说通过设置一个不存在的用户名重定向访问链接,如:

http://*@localhost/path

但我至少在FF16和Chrome22下测试是不行的,而且还有差异。

FF下的策略是只要验证成功过一次,其他带验证的地址发送给服务器还返回401的话,任何输入过的验证信息都会被用于自动向服务器发送以尝试验证,直到正确的通过验证为止。

Chrome下则是更换带验证信息地址后,首先会发一个清空了验证信息的请求到服务器,由服务器返回401请求验证,然后再自动发送刚刚更换了的验证信息到服务器,由于不是正确的,服务器仍会返回一个401,这时浏览器弹出验证请求提示输入,但这次输入如果还是错的(即服务器再次返回401时),浏览器就自动找到之前缓存了的正确验证信息进行发送,并得到成功验证的返回(非401)。

由此可见,默认的浏览器登陆框目前还是不靠谱的,各个浏览器对401处理的解释也不同。所以本希望利用HTTP丰富状态码进行RESTful的请求设计,就暂时不能使用401这个状态码了。不过作为替代方案可以使用403,代表请求这个资源在未通过验证,同时不再重复自动请求,而交由前端另行处理登陆提示即可。另可参考这篇:HTTP 401 Unauthorized or 403 Forbidden for a “disabled” user?