文章目录

  • 20220422
  • HTTP认证之基本认证——Basic(一)
  • 一、概述
  • 二、剖析
  • 三、缺陷
  • HTTP认证之基本认证——Basic(二)
  • HTTP认证之摘要认证——Digest(一)
  • 一、概述
  • 20230206 摘要认证中的cnonce和response如何获取?



在POSTMAN上看到有基本认证和摘要认证,都是带一个账号密码,不知道有什么区别。。。


zk digest认证_postman





文章目录

  • 20220422
  • HTTP认证之基本认证——Basic(一)
  • 一、概述
  • 二、剖析
  • 三、缺陷
  • HTTP认证之基本认证——Basic(二)
  • HTTP认证之摘要认证——Digest(一)
  • 一、概述
  • 20230206 摘要认证中的cnonce和response如何获取?


HTTP认证之基本认证——Basic(一)

一、概述

Basic认证是一种较为简单的HTTP认证方式,客户端通过明文(Base64编码格式)传输用户名和密码到服务端进行认证,通常需要配合HTTPS来保证信息传输的安全。

zk digest认证_http_02

二、剖析

  1. 当打开需要认证的页面时,会弹出一个对话框,要求输入用户名和密码
  2. 使用Fiddler监听请求(关于Fiddler与wireshark的区别可见:抓包工具:fiddler和wireshark对比),可以看到在未进行认证或认证失败的情况下,服务端会返回401 Unauthorized给客户端,并附带Challenge(质询),即在Response Header中添加WWW-Authenticate标头,浏览器识别到Basic后弹出对话框
    Realm表示Web服务器中受保护文档的安全域(比如公司财务信息域和公司员工信息域),用来指示需要哪个域的用户名和密码,用" "包括起来(截图中没有,但最好加上)。
  3. 输入正确的用户名和密码,认证成功后,浏览器会将凭据信息缓存起来,那么以后再进入时,无需重复手动输入用户名和密码。
    查看HTTP请求,可以看到Request Header中添加了Authorization标头,格式为:Authorization: <type> <credentials>
  • 类型为“Basic”
  • 凭证为“MTIzOjEyMw==”,是通过将“用户名:密码”格式的字符串经过的Base64编码得到的。而Base64不属于加密范畴,可以被逆向解码,等同于明文,因此Basic传输认证信息是不安全的

zk digest认证_HTTP_03

三、缺陷

  1. 用户名和密码明文(Base64)传输,需要配合HTTPS来保证信息传输的安全。
  2. 即使密码被强加密,第三方仍可通过加密后的用户名和密码进行重放攻击。
  3. 没有提供任何针对代理和中间节点的防护措施。
  4. 假冒服务器很容易骗过认证,诱导用户输入用户名和密码。
    接下来,我会带大家一起去了解更为安全的摘要认证——Digest。

参考文章:HTTP认证之基本认证——Basic(一)

HTTP认证之基本认证——Basic(二)

在HTTP认证之基本认证——Basic(一)中介绍了Basic认证的工作原理和流程,接下来就赶紧通过代码来实践一下,以下教程基于ASP.NET Core WebApi框架。

参考文章:HTTP认证之基本认证——Basic(二)

HTTP认证之摘要认证——Digest(一)

一、概述

Digest认证是为了修复基本认证协议的严重缺陷而设计的,秉承“绝不通过明文在网络发送密码”的原则,通过“密码摘要”进行认证,大大提高了安全性。

相对于基本认证,主要有如下改进:

  • 绝不通过明文在网络上发送密码
  • 可以有效防止恶意用户进行重放攻击
  • 可以有选择的防止对报文内容的篡改

需要注意的是,摘要认证除了能够保护密码之外,并不能保护其他内容,与HTTPS配合使用仍是一个良好的选择。以下是摘要认证的具体流程图:

zk digest认证_zk digest认证_04


看到上面出现了那么多之前没见过的参数,是不是有点慌(或是兴奋)?别着急,这里先给出一个概览:

  • WWW-Authentication:用来定义使用何种方式(Basic、Digest、Bearer(令牌token认证)等)去进行认证以获取受保护的资源
  • realm:表示Web服务器中受保护文档的安全域(比如公司财务信息域和公司员工信息域),用来指示需要哪个域的用户名和密码
  • qop:保护质量,包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略,(可以为空,但是)不推荐为空值
  • nonce:服务端向客户端发送质询(Challenge)时附带的一个随机数,这个数会经常发生变化。客户端计算密码摘要时将其附加上去,使得多次生成同一用户的密码摘要各不相同,用来防止重放攻击
  • nc:nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量。例如,在响应的第一个请求中,客户端将发送“nc=00000001”。这个指示值的目的是让服务器保持这个计数器的一个副本,以便检测重复的请求
  • cnonce:客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护
  • response:这是由用户代理软件计算出的一个字符串,以证明用户知道口令
  • Authorization-Info:用于返回一些与授权会话相关的附加信息
  • nextnonce:下一个服务端随机数,使客户端可以预先发送正确的摘要
  • rspauth:响应摘要,用于客户端对服务端进行认证
  • stale:当密码摘要使用的随机数过期时,服务器可以返回一个附带有新随机数的401响应,并指定stale=true,表示服务器在告知客户端用新的随机数来重试,而不再要求用户重新输入用户名和密码了

先不看这个了,先去搞其他的。。。


20230206 摘要认证中的cnonce和response如何获取?

问:摘要认证中的cnonce和response如何获取?

答:
cnonce 和 response 在 HTTP Digest 认证中是两个关键的参数,它们是通过计算来获得的。
cnonce 是 client nonce 的缩写,是一个随机生成的字符串,用于证明客户端参与了认证过程。
response 则是一个散列值,是通过使用特定的算法(如 MD5)对其他参数(如用户名,密码,cnonce 等)进行散列计算得到的。
具体来说,cnonce 可以使用随机数生成器或者当前时间等作为参数来生成,而 response 的计算方式则是固定的,详见 HTTP Digest 认证相关的文档。

问:如何用js获取它们?

答:
您可以使用 JavaScript 来生成 cnonce 和 response。
下面是一个生成 cnonce 的示例代码:
function generateCnonce() {
  let cnonce = '';
  const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  for (let i = 0; i < 32; i++) {
    cnonce += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return cnonce;
}
而生成 response 的代码可以通过使用散列函数(例如,使用 SHA-1 或 MD5 等)来计算:
function generateResponse(username, password, method, uri, nonce, nc, cnonce) {
  const ha1 = CryptoJS.MD5(username + ':' + realm + ':' + password);
  const ha2 = CryptoJS.MD5(method + ':' + uri);
  const response = CryptoJS.MD5(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2);
  return response;
}
注意:上面的代码仅供参考,实际的 HTTP Digest 认证可能会有更多的参数和限制,请仔细阅读相关的文档。

问:possible 是什么,是固定的,还是你随意写的?

答:
possible 是一个字符串常量,用于生成随机字符串的字符集。它是固定的,不是随意写的,但也可以根据实际需要进行修改。
它所代表的字符集包括了大写字母、小写字母和数字,共 62 个字符。如果需要,也可以更改为其他字符集。
如果生成的 cnonce 只用于特定的场景,则可以适当的调整字符集,使得生成的 cnonce 更适合实际需要。

问:CryptoJS是什么?

答:
CryptoJS 是一个开源的加密库,用于在 JavaScript 中执行常见的加密和哈希操作。它提供了一系列可以直接使用的加密算法,如 AES、SHA-1、MD5 等。
使用 CryptoJS 可以方便的实现常见的加密和哈希操作,而不需要对加密算法有深入的了解。
如果想要使用 CryptoJS,需要先在项目中引入 CryptoJS 的库文件,然后即可使用它提供的加密方法进行操作。
具体使用方法可以参考 CryptoJS 的文档:https://github.com/brix/crypto-js