Http Authenticate 介绍
周末给一个库添加http代理的支持,发现对http basic auth不甚了解,阅读了一下相关的文档,写篇备忘。
RFC 7235 [1] 描述了客户端(通常是浏览器)和服务器如何通过http进行身份认证的一些机制。客户端和 http代理之间也可以使用 http auth 来做验证。
验证流程
- 当客户端访问一个页面时,如果只有验证后才能访问,或者验证后有更多内容,服务器应该发送 401 Unauthorized,提出一个chanllenge,设定
WWW-Authenticate
header,并指定验证的 type 和 realm,具体定义下文有讲。 - 客户端这时通常应该提示用户输入密钥,一般是浏览器弹出用户名密码对话框供用户填写,然后使用
Authorization
header发送验证的密钥。如果验证通过的话,应该正常访问(200 OK),验证通过但是没有权限的话应该返回 403 Forbidden。 - 如果验证不通过,应该服务器返回401,客户端可以重试。
注意,如果客户端已经知道需要密钥访问,那么可以在第一个请求直接发送对应的密钥,这样就避免了 401 Unauthorized。
代理验证的不同
如果代理服务器需要验证的话,流程是类似的,有两点细节不同:
- 代理服务器应该发送407 Proxy Authentication Required 而不是 401。使用的headers也变成了 Proxy-Authenticate 和 Proxy-Authorization 。
- 服务器的头部 WWW-Authenticate 是 end-to-end 的,也就是代理服务器不应该篡改,应该原样传递。而代理服务器的Proxy-头部是 hop-by-hop 的,也就是不能向下传递。
实现细节
服务器或者代理服务器随着4XX发送的头部为
WWW-Authenticate: <type> realm=<realm>
or
Proxy-Authenticate: <type> realm=<realm>
其中 type 指定了使用的验证的类型,也就是用户名和密码加密方式的不同,IANA钦定了一批方法[2]。然鹅,一般来说常用的只有两个 Basic 和 Digest。而其中 Digest 的实现可能会要求服务器明文存储密码,于是大家又angry了[3],这里也不推荐使用。所以这里只介绍 Basic类型。
realm 指定了验证的领域,也就是说相同realm下的用户名和密码是一样的,如果你访问的两个页面在同一个realm,那么浏览器在第二次访问就不会问你密码了。
客户端发送对应的头部和密钥来获得访问权限
Authorization: <type> <credentials>
or
Proxy-Authorization: <type> <credentials>
其中,type就是刚刚的那个 Basic 或者 Digest。credentials 按照对应的方法计算。对于Basic类型 credentials = base64(username + ':' + password)
一个例子,假设用户名和密码分别是:aladdin和opensesame。那么客户端应该发送的header是:Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
需要注意的地方
- 因为http协议本身是无状态的,所以Auth应该是无状态的,所以每次请求都应该携带。
- 如果是http协议的话,对于Basic Auth,那么密码都是明文发送的,可以使用https来避免这个问题。
- 可以使用:https://username:password@www.example.com/ 这种形式来预先输入账号密码,但是这种形式已经不鼓励了。不过在设定一些环境变量时,比如 http_proxy,也只能用这种方法来制定用户名和密码
[1] 对应的RFC https://tools.ietf.org/html/rfc7235 [2] IANA 注册的auth类型 http://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml [3] 为什么不要使用digest验证 https://stackoverflow.com/questions/2384230/what-is-digest-authentication [4] MDN的文章还提供了如何让apache和nginx使用basic auth https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
相关文章
- HTTP Header里的Range和Content-Range参数[通俗易懂]
- Http通过header传递参数_http contenttype
- EasyDSS流媒体服务器软件(支持RTMP/HLS/HTTP-FLV/视频点播/视频直播)-正式环境安装部署攻略
- accept text/html,Accept_标题 | Headers_HTTP_参考手册_非常教程
- http缓存机制
- getUserMedia报错:新版本Chrome中getUserMedia接口在http下不再支持
- javascript获取当前是http还是https
- 深入理解 Http 请求、DNS 劫持与解析
- HTTP状态 500 - 内部服务器错误,Servlet[SpringMVC]的Servlet.init()引发异常
- 无法下载 http://dl.google.com/linux/chrome/deb/dists/stable/main/binary-amd64/Packages
- 性能测试(第1集)第7讲:HTTP协议介绍及抓包工具使用
- 如何架设一台简单(互联网HTTP)代理服务器?
- Akka(34): Http:Unmarshalling,from Json详解编程语言
- 服务Linux快速启动HTTP服务实现网络分享(linux启动http)
- 服务器Linux下简易配置HTTP服务器(linux配置http)
- Linux下HTTP抓包实战精要(http抓包linux)
- Linux搭建HTTP代理实现网络自由访问(linux搭建http代理)
- 服务器管理Linux中的HTTP服务器(linux中http)
- Linux下抓取HTTP包的技术实现(linux抓http包)
- HTTP错误代码详细介绍–8032
- 深入浅出:Linux 架构学习 HTTP 协议(http协议linux)
- HTTP错误代码详细介绍–8032
- 深入浅出Mongodb Http: 开箱即用的可扩展性数据库(mongodb http)
- Linux快速搭建超强HTTP服务器(linux搭建http服务器)
- 数据库使用HTTP连接Oracle数据库的简单操作(http连接oracle)
- 一步之遥从HTTP访问Oracle数据库(http访问oracle)
- 熟悉Redis,HTTP抓包,防止网络安全漏洞(redis,http抓包)
- asp.net客户端浏览器缓存的Http头介绍
- 基于.net中突破每客户端两个http连接限制的详细介绍