HTTP认证(前篇)

  本文着重介绍BasicDigestFormBase这三种认证方式

关于Basic认证及报文交互过程

关于Digest认证及摘要计算方法

关于FormBase认证及Session原理


HTTP/1.1的认证方式

  • Basic(基础)认证
  • Digest(摘要)认证
  • SSL客户端认证
  • FormBase(基于表单)认证

Web服务器

  • 报文字段:
    • WWW-Authenticate: 要求认证
    • Authorization: (请求)认证的信息
  • 状态码: 401 Unauthorized

代理服务器

  • 报文字段:
    • Proxy-Authenticate
    • Proxy-Authorization
  • 状态码: 407 Proxy Authentication Required

Basic认证

步骤

实践

工具:

  • http-server
  • telnet

设置参数:

  • ip: localhost
  • port: 8082
  • username: foo
  • password: bar
创建HTTP服务器
export NODE_HTTP_SERVER_USERNAME="foo"
export NODE_HTTP_SERVER_PASSWORD="bar"
http-server --port=8082
浏览器显示
报文首部
telnet localhost 8082

发送请求:

GET / HTTP/1.1
host: localhost

服务端返回401要求认证:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm=""
Date: Sun, 09 Feb 2020 18:31:27 GMT
Connection: keep-alive
Transfer-Encoding: chunked

将 base64(username:password),即b64(foo:bar)(=Zm9vOmJhcg==)发送:

GET / HTTP/1.1
host: localhost
Authorization: Basic Zm9vOmJhcg==

服务器认证成功后返回状态码200

HTTP/1.1 200 OK
server: ecstatic-3.3.2
cache-control: max-age=3600
last-modified: Thu, 30 Jan 2020 16:23:02 GMT
etag: W/"13372013-39766-2020-01-30T16:23:02.850Z"
content-length: 39766
content-type: text/html; charset=UTF-8
Date: Sun, 09 Feb 2020 18:31:31 GMT
Connection: keep-alive

  虽然似乎只要在浏览器中登录认证一次,就可以直接访问其他同域资源。
  但HTTP始终是一个无状态的协议(All requests and responses are independent),实际上每次请求都是需要认证身份的,只是浏览器已经根据缓存填好对应的认证信息了。

  因为base64编码并是加密处理,所以这种认证方式也并不安全,同时也不够灵活,所以不常用。



Digest认证

特点($md5(salt+passwd)$):

  • 用摘要保护密码(MD5单向散列)
  • Server产生随机数(对密码加盐)避免重放攻击replay attack
    • 即攻击者用捕获的认证凭据之后重新向服务器认证
  • Client产生随机数来支持对Server的认证

步骤

参数:

  • nonce: 一次性的随机字符串 [server –> client] (防止重放攻击)
  • cnonce(client nonce): 随机字符串 [client –> server]
  • nonceCount: 请求次数(进一步防止重放攻击)
  • qop: 质量保护(影响摘要算法的计算方式)
  • algorithm: 影响摘要计算方式
  • rspauth: server的应答摘要(用于让client验证server的身份)

摘要计算

计算参数:

  • username
  • password
  • HA1: 字符串变量(中间参数)
  • HA2
  • response: 计算结果
if `algorithm` is "MD5" or unspecified then
    `HA1` = MD5(username:realm:password)

else if `algorithm` is "MD5-sess" then
    `HA1` = MD5(MD5(username:realm:password):nonce:cnonce)


if `qop` is "auth" or unspecified then
    `HA2` = MD5(method:digestURI)

else if `qop` is "auth-int" then
    `HA2` = MD5(method:digestURI:MD5(entityBody))


if `qop` is "auth" or "auth-int" then
    `response` = MD5(`HA1`:nonce:nonceCount:cnonce:qop:`HA2`)

else if `qop` is unspecified then
    `response` = MD5(`HA1`:nonce:`HA2`)
计算练习

假定参数:

  • username: Mufasa
  • password: Circle Of Life
  • cnonce:
  • nonceCount: 00000001

已知server发来要求验证身份的报文相关信息为:

WWW-Authenticate: Digest realm="testrealm@host.com",
                        qop="auth,auth-int",
                        nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                        opaque="5ccc069c403ebaf9f0171e9517f40e41"

分析:

  • algorithm unspecified
    • -> HA1 = MD5(username:realm:password)
  • qop auth,auth-int(可认为只取auth
    • -> HA2=MD5(method:digestURI)
    • -> response=MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)
HA1 = MD5( "Mufasa:testrealm@host.com:Circle Of Life" )
    = 939e7578ed9e3c518a452acee763bce9

HA2 = MD5( "GET:/dir/index.html" )
    = 39aff3a2bab6126f332b942af96d3366

Response = MD5( "939e7578ed9e3c518a452acee763bce9:\
                dcd98b7102dd2f0e8b11d0f600bfb0c093:\
                00000001:0a4f113b:auth:\
                39aff3a2bab6126f332b942af96d3366" )
        = 6629fae49393a05397450978507c4ef1

  DIGEST认证提供了高于BASIC认证的安全等级,但是和HTTPS的客户端认证机制相比仍旧很弱。DIGEST认证提供防止密码被窃听的保护机制,但并不存在防止用户伪装的保护机制。



FormBase认证

  表单认证并没有一个统一的标准,但一般会用Cookie来管理SessionCookie字段用于弥补HTTP的无状态性

步骤

Session管理

  如果涉及到Session操作的,服务器则会返回Set-Cookie字段,这个字段中包含SessionID的信息,用来唯一标识一个session
  比如Tomcat返回的字段就是Set-Cookie: JSESSIONID=D43BA0A1EC5F9681B1BADCE67A5AA5C6

Session是如何运作的?

  在Tomcat容器中,由ManagerBase在内存中维护了一张<String, Session>表,通过提取请求中的JESSIONSID信息,来查找到当前的session的信息


请求中的JESSIONSID来自:

  • URI Parameters
  • Cookies
  • SSL SessionID

Session什么时候创建?

  在Tomcat容器中,只有当前session不存在时,且调用了getSession才会通过Manager创建,即仅访问静态资源是不会创建的
  而在默认情况下,JSP文件会调用getSession来跟踪会话,所以在这些JSP页面中,Cookie都会带有JSESSIONID字段

保护SessionID的常用手段?

  不难看出,一旦泄露了SessionID,对方就可以伪装成你的身份恶意操作了。


  通常一种安全的保存方法是,先利用给密码加盐(salt)的方式增加额外信息,再使用散列(hash)函数计算出散列函数后保存。

《图解HTTP》

  根据上文的Digest认证的思想,可以通过digest=md5(Salt+SessionID)的方式来加密传递的SessionID

  • Salt可以是时间戳等动态参数
  • Saltdigest一起发送,来避免重放攻击


参考

-------------本文结束-------------
0%