ASP.Net 身份登录重定向强制协议 (Https) [英] ASP.Net Identity Login Redirect Enforce Protocol (Https)

查看:34
本文介绍了ASP.Net 身份登录重定向强制协议 (Https)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望我只是遗漏了一些非常简单/显而易见的东西 - 为什么,更重要的是,如何在重定向到 Login 期间维护(或强制)协议?

举例说明:

  • 原始协议是https
  • 有人会认为这应该login之类的默认",但如图所示,重定向(似乎)没有维护它.

我尝试过的东西:

  • 有一个可以使用的 RequireHttps 属性,但是:

    1. 似乎奇怪"需要 2 次重定向才能到达那里"
    2. 在您有负载平衡器和/或在其他地方(不在服务器中)卸载"SSL 的情况下,这将是一个重定向循环(SSL 在客户端和前端之间net/ssl lb 和 http 到您的盒子/应用程序).这实际上是我的生产案例...

  • 我也已经设置了 IIS URL 重写(又名 规范 规则为整个站点的 https),这似乎被忽略"(太)(规则不检查https",否则会遇到相同的重定向循环).

  • 尝试在 LoginPath(在 CookieAuthenticationOptions 中)中设置绝对 URL 失败. 在负载平衡"/网络农场"环境中(比如 cert 所在的 ARR您的 ARR,而不是在您的主机中).在这种情况下,该检查总是返回false.

所以问题真的是关于如何解决这个问题的指导?

<小时>

更新 2

非常感谢 Richard 改变了我试图解决这个问题的方向".我最初是在寻找一种方法:

  • 设置/告诉 OWIN/Identity 使用安全 URL(明确地)并覆盖"它评估 LoginPath 的方式.处理 cookie 的 Secure(仅)选项以某种方式引导了我(如果我只能在 HTTPS 中明确说 cookie,那么它给我的印象是能够为 这样做LoginPath...一种或另一种方式)

  • 在我看来,一个hacky"的方式就是在客户端(Javascript)上处理它.

最后,Richard 的回答将我带到了 URL Rewriting(虽然仍然不在 LB 方面,因为这超出了我的控制范围).我目前正在工作(根据我的环境):

<match url=".*"/><条件><add input="{HTTP_CLUSTER_HTTPS}" pattern="^on$" negate="true"/><add input="{HTTP_CLUSTER_HTTPS}" pattern=".+" negate="true"/></条件><action type="Redirect" url="https://{HTTP_HOST}{SCRIPT_NAME}/{REQUEST_URI}" redirectType="SeeOther"/></规则>

在隧道尽头看到一些亮光.

<小时>

更新 3

再次感谢理查德的调查!最新的答案也让我进行了调查,结果发现有相当多的 SO 上的几篇帖子CookieApplyRedirectContext...所以现在这就是我所拥有的(特定于我的情况),也是我最初想要的:

app.UseCookieAuthentication(new CookieAuthenticationOptions{AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,LoginPath = new PathString("/Account/Login"),//这就是为什么.如果我可以明确设置这个,那么我(认为)我应该//能够明确地强制执行https(也......作为设置)//对于登录路径...CookieSecure = CookieSecureOption.Always,提供者 = 新的 CookieAuthenticationProvider{OnValidateIdentity = .....,OnApplyRedirect = 上下文 =>{乌里绝对乌里;if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out absoluteUri)){var path = PathString.FromUriComponent(absoluteUri);if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath){context.RedirectUri = context.RedirectUri.Replace("http:", "https:");}}context.Response.Redirect(context.RedirectUri);}}});

解决方案

出现此问题是因为您的应用程序正在发出到绝对 URL 的重定向.您可以通过以下两种方式之一解决此问题:在负载平衡器中或在应用程序本身中.

负载均衡器

配置您的负载均衡器以重写从 http 到 https 的重定向响应.如果您使用的是 ARR,以下规则(取自 此处) 应该可以工作:

<match serverVariable="RESPONSE_LOCATION" pattern="^http://[^/]+/(.*)"/><条件><add input="{ORIGINAL_HOST}" pattern=".+"/></条件><action type="Rewrite" value="http://{ORIGINAL_HOST}/{R:1}"/></规则>

其他负载均衡器将需要类似的配置.

申请

我们可以用相对 URL 替换 OWIN 在授权过程中重定向到的 URL,这意味着协议将保持浏览器之前使用的任何内容.

在 Owin 源代码中进行了一些挖掘以找到如何执行此操作,但是对应用程序启动的以下更改应该可以解决您的问题.首先,从您的启动配置中提取 CookieAuthenticationProvider 初始化.

变化:

app.UseCookieAuthentication(new CookieAuthenticationOptions{AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,LoginPath = new PathString("/Account/Login"),提供者 = 新的 CookieAuthenticationProvider{//在下面的步骤中移动这些选项...}});

致:

var cookieProvider = new CookieAuthenticationProvider{//... 现有应用程序中的选项};//修改重定向行为,将登录 URL 转换为相对var applyRedirect = cookieProvider.OnApplyRedirect;cookieProvider.OnApplyRedirect = 上下文 =>{if (context.RedirectUri.StartsWith("http://" + context.Request.Host)){context.RedirectUri = context.RedirectUri.Substring(context.RedirectUri.IndexOf('/', "http://".Length));}应用重定向(上下文);};app.UseCookieAuthentication(new CookieAuthenticationOptions){AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,LoginPath = new PathString("/Account/Login"),提供者 = cookieProvider});

虽然我们无法轻松了解重定向规则的设置位置,但 OWIN 使用委托来执行实际重定向.我在这里所做的是存储该委托,修改即将提供的 URL,然后再次调用它.

使用此选项,请确保您网站内的任何其他重定向和链接都是相对的.

Hopefully I'm just missing something really simple/obvious - why, and more importantly, how do you maintain (or force) the protocol during the redirect to Login?

To illustrate:

  • the original protocol is https
  • one would think this should be the "default" for something like login, but as shown, the redirect (seems) doesn't maintain it.

Stuff I tried:

  • There is a RequireHttps attribute that one could use, but:

    1. seems "weird" that it would take 2 redirects to get "there"
    2. in situations where you have a load balancer and/or have SSL "offloaded" elsewhere (not in server), then this would then be a redirect loop (SSL is between client and front-end net/ssl lb, and http to your box(es)/application). This is actually my production case...

  • I have already set IIS URL re-write as well (aka canonical rule to https for entire site), and that seems "ignored" (too) (rule does not check for "https" otherwise it suffers same redirect loop).

  • tried and failed to set absolute URL in LoginPath (in CookieAuthenticationOptions)..because you can't do that...

Thanks for advice or pointers...


Update

As to the "why"?

  1. in situations where you have a load balancer and/or have SSL "offloaded" elsewhere (not in server), then this would then be a redirect loop (SSL is between client and front-end net/ssl lb, and http to your box(es)/application). This is actually my production case..

Further tinkering got me to the above, as shown in this (localhost - my local dev box, not server) request sequence (the above issue manifests in a production load balanced environment where SSL processing is "up the stack" - e.g. ARR):

  • the protocol is in fact maintained
  • the issue seems exactly related to the situation where the application and the "infrastructure" don't "match". It seems similar to the situation where in code, you would do a Request.IsSecureConnection in a "load balanced"/"web farm" environment (say ARR where the cert is in your ARR, not in your host/s). That check will always return false in such a situation..

So the question really is on guidance on how to get around this?


Update 2

Many thanks to Richard for changing my "direction" in trying to resolve this. I originally was looking for a way to:

  • set/tell OWIN/Identity to use a secure URL (explicitly) and "override" the way it evaluates LoginPath. The Secure (only) option in handling cookies somehow led me that way (if I can explicitly say cookies in HTTPS only, then it sort of gave me an impression of being able to do so for LoginPath..one way or the other)

  • a "hacky" way in my mind was to just deal with it client side (Javascript).

In the end, Richard's answer took me to URL Rewriting (though still not on the LB side because that's beyond my control). I'm currently working off of (based on my environment):

<rule name="Redirect to HTTPS" stopProcessing="true">
    <match url=".*" />

    <conditions>
      <add input="{HTTP_CLUSTER_HTTPS}" pattern="^on$" negate="true" />
      <add input="{HTTP_CLUSTER_HTTPS}" pattern=".+" negate="true" />

    </conditions>
    <action type="Redirect" url="https://{HTTP_HOST}{SCRIPT_NAME}/{REQUEST_URI}" redirectType="SeeOther" />
</rule>

and see some light at the end of the tunnel.


Update 3

Awesome thanks again to Richard for the sleuthing! Latest answer got me sleuthing too and it turns out there's quite a few posts here on SO related to CookieApplyRedirectContext...so now this what I have in place (which is specific to my case), and is what I was originally going after:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
   AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
   LoginPath = new PathString("/Account/Login"),

   //This is why. If I could explicitly set this, then I (thought) I should
   //be able to explicitly enforce https (too..as a setting)
   //for the LoginPath...
   CookieSecure = CookieSecureOption.Always,

   Provider = new CookieAuthenticationProvider 
   {
      OnValidateIdentity = .....
      ,
      OnApplyRedirect = context =>
      {
         Uri absoluteUri;
          if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out absoluteUri))
          {
             var path = PathString.FromUriComponent(absoluteUri);
             if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath)
             {
                context.RedirectUri = context.RedirectUri.Replace("http:", "https:");
             }
           }
          context.Response.Redirect(context.RedirectUri);
        }
     }
});

解决方案

This problem is occurring because your application is issuing a redirect to an absolute URL. You can fix this in one of two ways, in the load balancer or in the application itself.

Load Balancer

Configure your load balancer to rewrite redirect responses from http to https. If you were using ARR, the following rule (taken from here) should work:

<rule name="forum-redirect" preCondition="IsRedirection" enabled="true">
  <match serverVariable="RESPONSE_LOCATION" pattern="^http://[^/]+/(.*)" />
  <conditions>
    <add input="{ORIGINAL_HOST}" pattern=".+" />
  </conditions>
  <action type="Rewrite" value="http://{ORIGINAL_HOST}/{R:1}" />
</rule>

Other load balancers will require similar configuration.

Application

We can replace the URL that OWIN redirects to in the authorization process with a relative URL, which means the protocol will stay as whatever the browser was previously using.

It took a bit of digging in the Owin source to find how to do this, but the following change to your Application startup should solve your problems. First, extract the CookieAuthenticationProvider initialisation from your startup config.

Change:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider 
    {
        // Move these options in the step below...
    }
});

To:

var cookieProvider = new CookieAuthenticationProvider
{ 
    // ... Options from your existing application
};
// Modify redirect behaviour to convert login URL to relative
var applyRedirect = cookieProvider.OnApplyRedirect;
cookieProvider.OnApplyRedirect = context =>
{
    if (context.RedirectUri.StartsWith("http://" + context.Request.Host))
    {
        context.RedirectUri = context.RedirectUri.Substring(
            context.RedirectUri.IndexOf('/', "http://".Length));
    }
    applyRedirect(context);
};

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = cookieProvider
});

While we can't get at where the redirection rule is set easily, OWIN uses a delegate to perform the actual redirect. What I've done here is stored that delegate, modified the URL it is about to be given, and then called it again.

With this option, ensure that any other redirects and links within your site are relative.

这篇关于ASP.Net 身份登录重定向强制协议 (Https)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆