用WWW-Authenticate实现登录验证
今天在研究HTTP协议时发现一个叫WWW-Authenticate的头字段,可以用于实现登录验证。它是在
RFC 2617中定义的。
用法很简单,将状态码设为401,在响应头中加上这个字段即可:
浏览器接收到这个响应后,就会弹出这样的对话框:
然后用户输入用户名和密码,点确定进行登录。
此时用户名和密码会以冒号:分隔,并进行base64编码,在请求头中以Authorization字段发出:
服务器只要获取Authorization字段,按base64解码,再以冒号区分用户名和密码,即可验证是否正确了。由于用户名一般不允许包含冒号,所以即使密码中输入了冒号也没关系。
一个简单的实现如下:
当然,如果你直接这么实现的话,你的用户就惨了。因为HTTP协议是不安全的,任何窃听者都能获取Authorization字段,然后就能很轻易地获取密码了,所以这种简单的实现只能用于HTTPS。
为了确保用户的密码不被窃取,用户的登录信息应该被加密。而实际上并不需要完整的登录信息,只要一个可用于验证的摘要即可,于是服务器可以指定浏览器生成一个Digest。
所需的参数很多,有服务器生成的每次均唯一的字符串、用户请求的URI、请求序列号等。浏览器根据这些参数,与用户名、密码的MD5值用冒号组合起来,再求一次MD5,作为整个的摘要。
这样就非常安全了,只是对服务器负担较大,因为要生成一个随机字符串,还得记录请求序列号等。
好在有些库已经提供了这些功能,所以可以直接使用现成的。
用法很简单,将状态码设为401,在响应头中加上这个字段即可:
引用:
WWW-Authenticate: Basic realm="testrealm@keakon.cn"
然后用户输入用户名和密码,点确定进行登录。
此时用户名和密码会以冒号:分隔,并进行base64编码,在请求头中以Authorization字段发出:
引用:
Authorization: Basic base64编码过的登录信息
一个简单的实现如下:
The py code:
- def get(self):
- authorization = self.request.headers.get('Authorization', '')
- if authorization and authorization[:6] == 'Basic ':
- user, password = b64decode(authorization[6:]).split(':', 1)
- if user == 'admin' and password == 'fuckgfw':
- self.echo('hello, ' + user)
- return
- self.set_status(401)
- self.header['WWW-Authenticate'] = 'Basic realm="testrealm@keakon.cn"'
当然,如果你直接这么实现的话,你的用户就惨了。因为HTTP协议是不安全的,任何窃听者都能获取Authorization字段,然后就能很轻易地获取密码了,所以这种简单的实现只能用于HTTPS。
为了确保用户的密码不被窃取,用户的登录信息应该被加密。而实际上并不需要完整的登录信息,只要一个可用于验证的摘要即可,于是服务器可以指定浏览器生成一个Digest。
所需的参数很多,有服务器生成的每次均唯一的字符串、用户请求的URI、请求序列号等。浏览器根据这些参数,与用户名、密码的MD5值用冒号组合起来,再求一次MD5,作为整个的摘要。
这样就非常安全了,只是对服务器负担较大,因为要生成一个随机字符串,还得记录请求序列号等。
好在有些库已经提供了这些功能,所以可以直接使用现成的。