HTTP Basic和Digest认证介绍与计算
一、说明
web用户认证,最开始是get提交+把用户名密码存放在客户端的cookie中的形式;在意识到这样不安全之后逐渐演变成了post提交+把用户凭证放到了服务端的session中的形式(当然sessionid还在cookie中)。
不过其实最初给http设计的认证方式,既不是“get+cookie”也不是“post+session”,而是Basic和Digest。但Basic和Digest并不流行我想主要是因为麻烦,一是说Basic和Digest使用的Authorization头并不会被浏览器自动发往服务器,二是说对于Digest计算很麻烦。
二、Basic认证形式
2.1 Basic认证请求示例
请求示例如下,主要是Authorization头(位置不重要,http头一般都不分先后)
GET /GetDeviceInfo HTTP/1.1
Host: 192.168.220.128
Authorization: Basic YWRtaW46MTIzNDU2
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept-Encoding: gzip, deflate
Accept: */*
Cache-Control: no-cache
Cookie: Secure
Connection: close
2.2 Basic认证计算方法
前边请求Authorization头的YWRtaW46MTIzNDU2,实际上是用户名admin密码123456使用以下计算方法得到:
base64(username:password)
Python计算代码如下:
import base64 def get_basic_authorization_header_value(username,password):
# base64编码前后都(要)是字节码形式
authorization_value = base64.b64encode((f"{username}:{password}").encode()).decode()
authorization_header_value = f"Basic {authorization_value}"
return authorization_header_value
三、Digest认证形式
3.1 Digest认证请求示例
GET /GetDeviceInfo HTTP/1.1
Host: 192.168.220.128
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0
Authorization: Digest username="admin",realm="TVT API Test Tool",nonce="d4f95e85dc5a39a4914db61b67878f5b",uri="GetDeviceInfo",algorithm="MD5",cnonce="d4f95e85dc5a39a4914db61b67878f5b",nc=00000001,qop="auth",response="1cc4cf126d3c4a70d2de34c5d8c2943c"
Accept-Encoding: gzip, deflate
Accept: */*
Cache-Control: no-cache
Cookie: Secure
Connection: close
username----系统用户名;客户端自行填充
realm----领域;服务端通过WWW-Authenticate头返回内容可以自己随便定,但其目的是用于提示客户端当前是什么系统,所以规范来说应类似于“myhost@testrealm.com”的形式。
nonce----服务端通过WWW-Authenticate头返回的随机数
uri----请求接口或资源(似乎规范来说应用GET或POST后的一样,上边例子中少了/是因为服务端没按规范实现)
algorithm----后边response用的计算方法
cnonce----client nonce,客户端生成的随机数
nc----nonce count,用于标识进行请求的次数。(但你一直不变服务端也不会管你对不对)
qop----quality of protection,进一步限定response的计算方法,服务端通过WWW-Authenticate头返回。
response----认证最主要的值,前面各字段除algorithm外全要参与该值的计算。
3.2 Digest认证计算方法
在最开始的RFC 2069中规定response计算方法如下:
HA1 = MD5(username:realm:password)
HA2 = MD5(method:uri)
response = MD5(HA1:nonce:HA2)
随后的RFC 2617对计算方法进行了增强,规定计算方法如下(当algorithm值为MD5或未指定、qop未指定时等同RFC 2069):
# HA1部分
# 当algorithm值为"MD5"或未指定时,HA1计算方法如下
HA1 = MD5(username:realm:password)
# 当algorithm值为"MD5-sess"时,HA1计算方法如下
HA1 = MD5(MD5(username:realm:password):nonce:cnonce) # HA2部分
# 当qop值为"auth"或未指定时,HA2计算方法如下
HA2 = MD5(method:uri)
# 当qop值为"auth-int"时,HA2计算方法如下;entityBody是指整个body(?)
HA2 = MD5(method:uri:MD5(entityBody)) # response部分
# 当qop值为"auth"或"auth-int"时,response计算方法如下
response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)
# 当qop未指定时,response计算方法如下
response = MD5(HA1:nonce:HA2)
Python计算代码如下:
import hashlib # body初始值不要是None,不然下边encode时会报错
def get_basic_authorization_header_value(username, password, uri, method, realm, nonce, nc, cnonce, algorithm=None, qop=None, body=""):
response_value = calc_digest_response_value(username, password, uri, method, realm, nonce, nc, cnonce, algorithm, qop, body)
authorization_header_value = f'Digest username="{username}",realm="{realm}",nonce="{nonce}",uri="{uri}",algorithm="{algorithm}",cnonce="{cnonce}",nc={nc},qop="{qop}",response="{response_value}"',
return authorization_header_value def calc_digest_response_value(username, password, uri, method, realm, nonce, nc, cnonce, algorithm=None, qop=None, body=""):
# HA1部分
# 当algorithm值为"MD5"或未指定时,HA1计算方法如下
if algorithm == "MD5" or algorithm == "" or algorithm is None:
HA1 = hashlib.md5((f"{username}:{realm}:{password}").encode()).hexdigest()
# 当algorithm值为"MD5-sess"时,HA1计算方法如下
elif algorithm == "MD5-sess":
HA1 = hashlib.md5((f"{username}:{realm}:{password}").encode()).hexdigest()
HA1 = hashlib.md5((f"{HA1}:{nonce}:{cnonce}").encode()).hexdigest()
else:
response_value = '"the value of algorithm must be one of "MD5"/"MD5-sess"/""/None'
return response_value # HA2部分
# 当qop值为"auth"或未指定时,HA2计算方法如下
if qop == "auth" or qop == "" or qop is None:
HA2 = hashlib.md5((f"{method}:{uri}").encode()).hexdigest()
# 当qop值为"auth-int"时,HA2计算方法如下;entityBody是不是指整个body我其实不太确定
elif qop == "auth-int":
HA2 = hashlib.md5((f"{body}").encode()).hexdigest()
HA2 = hashlib.md5((f"{method}:{uri}:{HA2}").encode()).hexdigest()
else:
response_value = '"the value of qop must be one of "auth"/"auth-int"/""/None'
return response_value # response部分
# 当qop值为"auth"或"auth-int"时,response计算方法如下
if qop == "auth" or qop == "auth-int":
response_value = hashlib.md5((f"{HA1}:{nonce}:{nc}:{cnonce}:{qop}:{HA2}").encode()).hexdigest()
# 当qop未指定时,response计算方法如下
elif qop == "" or qop is None:
response_value = hashlib.md5((f"{HA1}:{nonce}:{HA2}").encode()).hexdigest()
else:
response_value = "unknown error"
return response_value
参考:
https://en.wikipedia.org/wiki/Digest_access_authentication
https://tools.ietf.org/html/rfc2069
https://tools.ietf.org/html/rfc2617
HTTP Basic和Digest认证介绍与计算的更多相关文章
- HTTP认证模式:Basic and Digest Access Authentication
一. Basic 认证 客户端以“ : ”连接用户名和密码后,再经BASE64编码( Base64 Content-Transfer-Encoding )通过Authorization请求头发送该密文 ...
- http 登录Digest认证相关知识
Digest access authentication https://en.wikipedia.org/wiki/Digest_access_authentication Digest acces ...
- 【ASP.NET Web API2】Digest认证
Digest摘要认证 对于Basic认证方案来说,被传输的认证凭证仅仅采用Base64编码,所以包含密码的认证凭证基本上可以视为明文传输.Digest认证在此基础上进行了改善,在一定程度上提高了安全系 ...
- OAuth2.0认证介绍
OAuth2.0鉴权 返回 目录 [隐藏] 1 腾讯微博OAuth2.0认证介绍 2 获取accesstoken的两种方式 2.1 1.Authorization code grant 2.1.1 第 ...
- 批量检测GoAhead系列服务器中Digest认证方式的服务器弱口令
最近在学习用python写爬虫工具,某天偶然发现GoAhead系列服务器的登录方式跟大多数网站不一样,不是采用POST等方法,通过查找资料发现GoAhead是一个开源(商业许可).简单.轻巧.功能强大 ...
- 使用crypt配置Basic Auth登录认证
简介 Basic Auth用于服务端简单的登录认证,通常使用服务器Nginx.Apache本身即可完成.比如我们要限定某个域名或者页面必须输入用户名.密码才能登录,但又不想使用后端开发语言,此时Bas ...
- 本文将介绍“数据计算”环节中常用的三种分布式计算组件——Hadoop、Storm以及Spark。
本文将介绍“数据计算”环节中常用的三种分布式计算组件——Hadoop.Storm以及Spark. 当前的高性能PC机.中型机等机器在处理海量数据时,其计算能力.内存容量等指标都远远无法达到要求.在大数 ...
- 任务31:课时介绍 & 任务32:Cookie-based认证介绍 &任务33:34课 :AccountController复制过来没有移除[Authorize]标签
任务31:课时介绍 cookie-based网站这边的认证 jwt基于移动端和前后端分离的项目,jwt有一些独特的优势 jwt在asp.net core中的实现机制,了解实现机制并进行扩展.比如非标准 ...
- 接口开发---basic auth接口认证
开发中遇到了basic auth来认证的案例,这里总结一下: Basic Auth简单点说明就是每次请求API时都提供用户的username和password.[base64encode(userna ...
随机推荐
- 前端好用js库
1.pubsub-js: PubSubJS is a topic-based publish/subscribe library written in JavaScript. 评价:做发布订阅超级简单 ...
- SlidingMenu第三篇 --- SlidingMenu使用介绍
在Activity中通过SlidingMenu的构造方法,直接设置侧滑菜单 public class Main2Activity extends Activity { @Override protec ...
- 使用session和cookie实现用户登录:一个登录页面,一个servlet,一个登录成功页面
文件目录 1.登录页面 <%@ page language="java" contentType="text/html; charset=utf-8" p ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 为KindEditor 添加“一键去除空格功能”
环境说明:KindEditor 4.1.11 一.确定你在使用KindEditor时,引用的是kindEditor-all.js,找到任何一个已经存在的功能,例如,清除HTML代码,我在做的时候本来 ...
- 记一次JAVAWEB项目部署
需求 原本服务器上tomcat部署了一个javaweb项目在80端口,这次要部署另一个javaweb项目在8090端口,或者同时部署在同一端口不同目录下. 解决方法 不同端口部署 不同端口部署我们需要 ...
- iOS QQ 扫一扫 捷径URL
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- TYVJ P1039 【忠诚2】
题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了 ...
- UVA - 11468 (AC自动机+动态规划)
建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...
- 页面对象(Page Object)模式
内容转载自 https://www.cnblogs.com/yytesting/p/6973474.html 页面对象(Page Object)模式是目前自动化测试领域普遍使用的设计模式之一,此模式可 ...