内容简介:可能有人知道如果需要在首先用户通过
前言
可能有人知道 Cookie
的生成由 machineKey
有关, machineKey
用于决定 Cookie
生成的算法和密钥,并如果使用多台服务器做负载均衡时,必须指定一致的 machineKey
用于解密,那么这个过程到底是怎样的呢?
如果需要在 .NETCore
中使用 ASP.NETCookie
,本文将提到的内容也将是一些必经之路。
抽丝剥茧,一步一步分析
首先用户通过 AccountController->Login
进行登录:
它调用了 SignInManager
的 PasswordSignInAsync
方法,该方法代码如下(有删减):
想浏览原始代码,可参见官方的 Github
链接:https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Owin/SignInManager.cs#L235-L276
可见它先需要验证密码,密码验证正确后,它调用了 SignInOrTwoFactor
方法,该方法代码如下:
该代码只是判断了是否需要做双重验证,在需要双重验证的情况下,它调用了 AuthenticationManager
的 SignIn
方法;否则调用 SignInAsync
方法。 SignInAsync
的源代码如下:
可见,最终所有的代码都是调用了 AuthenticationManager.SignIn
方法,所以该方法是创建 Cookie
的关键。
AuthenticationManager
的实现定义在 Microsoft.Owin
中,因此无法在 ASP.NETIdentity
中找到其源代码,因此我们打开 Microsoft.Owin
的源代码继续跟踪(有删减):
AuthenticationManager
的 Github
链接如下:https://github.com/aspnet/AspNetKatana/blob/c33569969e79afd9fb4ec2d6bdff877e376821b2/src/Microsoft.Owin/Security/AuthenticationManager.cs
可见它用到了 AuthenticationResponseGrant
,继续跟踪可以看到它实际是一个属性:
发现它其实是设置了 SignInEntry
,继续追踪:
其中, _context
的类型为 IOwinContext
, OwinConstants.Security.SignIn
的常量值为 "security.SignIn"
。
跟踪完毕……
啥?跟踪这么久,居然跟丢啦!?
当然没有!但接下来就需要一定的技巧了。
原来, ASP.NET
是一种中间件( Middleware
)模型,在这个例子中,它会先处理 MVC
中间件,该中间件处理流程到设置 AuthenticationResponseGrant
/ SignInEntry
为止。但接下来会继续执行 CookieAuthentication
中间件,该中间件的核心代码在 aspnet/AspNetKatana
仓库中可以看到,关键类是 CookieAuthenticationHandler
,核心代码如下:
这个原始函数有超过 200
行代码,这里我省略了较多,但保留了关键、核心部分,想查阅原始代码可以移步 Github
链接:https://github.com/aspnet/AspNetKatana/blob/0fc4611e8b04b73f4e6bd68263e3f90e1adfa447/src/Microsoft.Owin.Security.Cookies/CookieAuthenticationHandler.cs#L130-L313
这里挑几点最重要的讲。
与 MVC
建立关系
建立关系的核心代码就是第一行,它从上文中提到的位置取回了 AuthenticationResponseGrant
,该 Grant
保存了 Claims
、 AuthenticationTicket
等 Cookie
重要组成部分:
继续查阅 LookupSignIn
源代码,可看到,它就是从上文中的 AuthenticationManager
中取回了 AuthenticationResponseGrant
(有删减):
如此一来,柳暗花明又一村,所有的线索就立即又明朗了。
Cookie的生成
从 AuthenticationTicket
变成 Cookie
字节串,最关键的一步在这里:
在接下来的代码中,只提到使用 CookieManager
将该 Cookie
字节串添加到 Http
响应中,翻阅 CookieManager
可以看到如下代码:
有兴趣的朋友可以访问 Github
看原始版本的代码:https://github.com/aspnet/AspNetKatana/blob/0fc4611e8b04b73f4e6bd68263e3f90e1adfa447/src/Microsoft.Owin/Infrastructure/ChunkingCookieManager.cs#L125-L215
可见这个实现比较……简单,就是往 Response.Headers
中加了个头,重点只要看 TicketDataFormat.Protect
方法即可。
逐渐明朗
该方法源代码如下:
可见它依赖于 _serializer
、 _protector
、 _encoder
三个类,其中, _serializer
的关键代码如下:
其本质是进行了一次二进制序列化,并紧接着进行了 gzip
压缩,确保 Cookie
大小不要失去控制(因为 .NET
的二进制序列化结果较大,并且微软喜欢搞 xml
,更大:joy:)。
然后来看一下 _encoder
源代码:
可见就是进行了一次简单的 base64-url
编码,注意该编码把 =
号删掉了,所以在 base64-url
解码时,需要补 =
号。
这两个都比较简单,稍复杂的是 _protector
,它的类型是 IDataProtector
。
IDataProtector
它在 CookieAuthenticationMiddleware
中进行了初始化,创建代码和参数如下:
注意它传了三个参数,第一个参数是 CookieAuthenticationMiddleware
的 FullName
,也就是 "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware"
,第二个参数如果没定义,默认值是 CookieAuthenticationDefaults.AuthenticationType
,该值为定义为 "Cookies"
。
但是,在默认创建的 ASP.NET MVC
模板项目中,该值被重新定义为 ASP.NETIdentity
的默认值,即 "ApplicationCookie"
,需要注意。
然后来看看 CreateDataProtector
的源码:
可见它先从 IAppBuilder
的 "security.DataProtectionProvider"
属性中取一个 IDataProtectionProvider
,否则使用 DpapiDataProtectionProvider
。
我们翻阅代码,在 OwinAppContext
中可以看到,该值被指定为 MachineKeyDataProtectionProvider
:
文中的 Constants.SecurityDataProtectionProvider
,刚好就被定义为 "security.DataProtectionProvider"
。
我们翻阅 MachineKeyDataProtector
的源代码,刚好看到它依赖于 MachineKey
:
最终到了我们的老朋友 MachineKey
。
逆推过程,破解Cookie
首先总结一下这个过程,对一个请求在 Mvc
中的流程来说,这些代码集中在 ASP.NETIdentity
中,它会经过:
-
AccountController
-
SignInManager
-
AuthenticationManager
-
设置
AuthenticationResponseGrant
然后进入 CookieAuthentication
的流程,这些代码集中在 Owin
中,它会经过:
-
CookieAuthenticationMiddleware
(读取AuthenticationResponseGrant
) -
ISecureDataFormat
(实现类:SecureDataFormat<T>
) -
IDataSerializer
(实现类:TicketSerializer
) -
IDataProtector
(实现类:MachineKeyDataProtector
) -
ITextEncoder
(实现类:Base64UrlTextEncoder
)
这些过程,结果上文中找到的所有参数的值,我总结出的“祖传破解代码”如下:
运行前请设置好 app.config
/ web.config
中的 machineKey
节点,并安装 NuGet
包: Microsoft.Owin.Security
,运行结果如下(完美破解):
学习方式有很多种,其中看代码是我个人非常喜欢的一种方式,并非所有代码都会一马平川。像这个例子可能还需要有一定 ASP.NET
知识背景。
注意这个“祖传代码”是基于 .NETFramework
,由于其用到了 MachineKey
,因此无法在 .NETCore
中运行。我稍后将继续深入聊聊 MachineKey
这个类,看它底层代码是如何工作的,然后最终得以在 .NETCore
中直接破解 ASP.NETIdentity
中的 Cookie
,敬请期待!
最后,在新的一年里,祝大家阖家欢乐,鼠年大吉!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 实战生成对抗网络(二):生成手写数字
- 实战生成对抗网络[2]:生成手写数字
- 020.Python生成器和生成器函数
- faker生成器生成虚拟数据的Python模块
- 利用代码生成工具生成基于ABP框架的代码
- 数据生成工具 ZenData 1.4 发布,内置国家、日期、时间格式,支持文章生成
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java EE WEB开发与项目实战
李俊青 / 华中科技大学出版社 / 2011-11 / 59.80元
本书采用工程案例的形式,将日常Java EE项目开发所涉及的技术要点进行了解析,系统介绍了Apache的安装、Tomcat的安装、虚拟主机的配置、开发工具的搭配使用、验证码的使用、过滤器的使用、密码的加密与解密、JavaMail邮件发送、Web在线编辑器的使用、文件上传、数据库连接池、Ajax与Servlet的身份认证、Struts框架的应用、JSF框架的应用、Spring框架的应用、Hibern......一起来看看 《Java EE WEB开发与项目实战》 这本书的介绍吧!