由于遵从性原因,我们必须关闭Web服务器上某些密码和SSL2的支持.这不是一个真正的问题,但我们也希望在他们成功登录网站后通知他们,我们建议在他们的浏览器中打开TLS 1.2,以防他们尚未使用TLS 1.2连接到服务器.所以我的问题是:

How can I detect the protocol and cipher used in an https request to an ASP.net (MVC 4) application running in IIS?

我知道有很多方法可以将SCHANNEL请求记录到事件日志(log)中,然后再次读取它们,但这听起来很难听.

我已经看到System.Net.Security.SslStream具有我需要的属性,例如:Cipher算法rithm, Hash算法rithm, KeyExchange算法rithm & SslProtocol,但我不确定在mvc4应用程序的控制器操作中从哪里可以获得这些属性.

推荐答案

坏消息是,正如ILSpy所确定的那样,无法从ASP.NET内的任何地方到达System.Net.SslStream实例.该类用于针对网络的直接编程,例如通过WCF框架.从ASP.NET(无论是使用System.Web还是在IIS或HttpListener之上使用OWIN),您能做的最好的事情就是获取一个服务器变量(see list of IIS server variables),以确定连接是否受到与客户端协商的任何安全传输的保护.

就在web请求期间从事件日志(log)中确定读取数据而言...这似乎很可怕.但如果你能让它工作,请分享代码.:)

或者,您可以try 实现自己的Owin主机(又名web服务器!)下面用SslStream.也许吧P有关SslStream编程的详细介绍,请参见this article.

但是,由于您已经能够关闭服务器上的某些协议(我假设是在this article中)...您可以在两个不同的子域上设置站点,例如www.example.comsecure.example.com,其中前者是一个普通的web服务器,后者配置为仅接受TLS 1.2连接.然后,您将编写一些 bootstrap 逻辑,从www.example.com获得服务,并try 向secure.example.com/securityUpgradeCheck发出AJAX请求(可能带有风格优美的微调器动画和"请稍候,try 保护此连接"文本,以打动您的用户:).如果该请求成功,用户可以重定向到secure.example.com(可能是永久性的,因为该用户代理随后已知支持TLS 1.2,除非用户出于某种原因更改其浏览器设置).

为了增加影响,请为安全域订购EV SSL证书,这样您的用户就会注意到安全方面的升级.:)

在编写自定义(本地)ISAPI过滤(或扩展)以通过Schannel API获取此信息的理论基础上,我做了更深入的研究.起初我满怀希望,因为我发现了一个函数HSE_REQ_GET_SSPI_INFO,它将返回SSPICtxtHandle struct ,您可以通过EXTENSION_CONTROL_BLOCKServerSupportFunction函数从自定义ISAPI扩展调用它.事实证明,CtxtHandle struct 表示Schannel上下文,can为您提供对SECPKG_ATTR_CONNECTION_INFO属性的引用,您可以使用该属性检索SSL连接级信息(据我所知,这与.NET的SslStream类中出现的信息相同).然而,令人遗憾的是,Microsoft anticipated that possibilitythis information is only available if you are using client certificates.决定,this information is only available if you are using client certificates.的行为是"有意为之".

我在长期搜索MSDN时发现了一个(本地)SSPI函数,即QueryContextAttributes (Schannel),其中may可以工作.我还没有try 过,它可能会因为与上面链接的ISAPI API限制相同的"设计"原因而失败.不过,这可能值得一试.如果你想探索这条路由,这里是an example of an ISAPI extension.实际上,使用这种方法,您可以使用较新的IIS 7.0+SDK编写IIS模块.

但是,假设你没有要求客户证书的奢侈条件,而且"远射"是行不通的,那绝对只剩下两种 Select .

  1. 使用不同的web服务器(Apache等),在相同的物理/虚拟机上运行,但在不同的端口上运行,等等(根据我们在 comments 中的讨论,因为您无法启动另一台机器).如果您只想给客户机一条信息性消息,那么这种方法加上AJAX请求可能就足够了.是的,一个不同的端口很可能会被某个地方的防火墙屏蔽,但嘿——无论如何,这只是一条可选的信息消息.
  2. 依赖于系统事件日志(log)的半脆性方法.Enable Schannel event logging,然后编写一些事件日志(log)查询代码,try 将请求与最后记录的Schannel事件相关联.请注意,您需要找到一种方法来可靠地将放入事件日志(log)中的任何内容与当前HTTP请求相关联,因此,您might还需要编写一个ISAPI过滤/扩展或IIS模块(在本例中为IIS模块)来查找SCANNEL上下文句柄(我假设相关性将基于此).

顺便问一下,您的负载平衡器是否配置为执行任何SSL拦截?因为这整件事无论如何都没有意义...只是考虑一下.

UPDATE:年来,Schannel logging取得了以下成就:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Schannel" Guid="{1F678132-5938-4686-9FDC-C8FF68F15C85}" /> 
    <EventID>36880</EventID> 
    <Version>0</Version> 
    <Level>4</Level> 
    <Task>0</Task> 
    <Opcode>0</Opcode> 
    <Keywords>0x8000000000000000</Keywords> 
    <TimeCreated SystemTime="2014-08-13T02:59:35.431187600Z" /> 
    <EventRecordID>25943</EventRecordID> 
    <Correlation /> 
    <Execution ProcessID="928" ThreadID="12912" /> 
    <Channel>System</Channel> 
    <Computer>**********</Computer> 
    <Security UserID="S-1-5-18" /> 
  </System>
  <UserData>
    <EventXML xmlns:auto-ns3="http://schemas.microsoft.com/win/2004/08/events" xmlns="LSA_NS">
      <Type>client</Type> 
      <Protocol>TLS 1.2</Protocol> 
      <CipherSuite>0x3c</CipherSuite> 
      <ExchangeStrength>2048</ExchangeStrength> 
    </EventXML>
  </UserData>
</Event>

这可以直接从托管代码中读出.不幸的是,我认为userid只对应于IIS工作进程SID,但是假设您可以提出某种关联启发式方法,您可以设置一个后台线程来不断轮询事件日志(log),并为您提供最近建立的客户端握手列表(可能使用ConcurrentDictionary).

那里就这样.我再也不好奇了.我做完了P

Asp.net相关问答推荐

如何从 JavaScript 调用 C# 函数?

ASP MVC 授权除少数之外的所有操作

业务线应用程序:F# 会让我的生活变得轻松吗?

Asp.Net 会话在 ashx 文件中为空

从 GUID 中删除破折号是个好主意吗?

如何通过后面的代码不显示

Jquery asp.net 按钮单击事件通过 ajax

免费的 ASP.Net 和/或 CSS 主题

如何解决 Kerberos 双跳问题?

.Net Standard 2.0 类库是否有通用配置文件?

有条件地排除 ASP.NET WebForms 中的一个 html 块

HttpContext.Current 在 MVC 4 项目中未解决

HttpResponse.End 或 HttpResponse.Close 与 HttpResponse.SuppressContent

如何使用 encodeURIComponent() 解码在 JS 中编码的 HTML?

如何在 .NET Core 中实现 DbContext 连接字符串?

在 Asp.Net Core 中动态更改连接字符串

LinkBut​​ton 向 OnClick 后面的代码发送值

如何在服务器控件属性中使用 ASP.NET <%= 标签?

MVC4 - 当优化设置为 true 时Bundle 不起作用

ASP.NET MVC3 局部视图命名约定