繁体   English   中英

表单身份验证+ ASP.NET MVC绝对ReturnURL

[英]Forms authentication + ASP.NET MVC absolute ReturnURL

我在服务器a上有一个中央身份验证应用程序。 服务器b在同一域上具有一个或多个需要从服务器a进行身份验证的应用程序。 设置起来很容易,以便服务器b应用重定向到服务器a。 要使ReturnURL成为绝对值不是那么容易。

这是皱纹。 服务器b上的消费应用程序具有两个控制器,一个为公共控制器,另一个为安全控制器。 如果将[authorize]装饰放在公众的某个动作上(这是默认控制器),我将获得正确的绝对URL。 但是,如果它在它自己的控制器中,则会得到一个相对URL。

我可以在使用中的应用程序中拦截请求前事件,但是我需要使网站的某些部分公开,而不是整个粉碎。

有想法吗?

标准AuthorizeAttribute的工作方式是,如果请求未通过身份验证,则将响应状态代码设置为401。 这将启动默认身份验证模块对未授权请求的标准响应。 我假设您使用的是基于表单的身份验证,该身份验证将基于请求中的URL构建返回URL。 在这种情况下,可能是相对URL。

您可以做的一件事是,不必依靠内置行为,而可以实现SSOAuthorizeAttribute,它扩展了AuthorizeAttribute类并覆盖了OnAuthorization。 然后,您可以从Web配置中的forms元素中提取loginUrl,并构建自己的RedirectResult,并从AuthorizationContext参数中的HttpContext.Request.Url.AbsoluteUri属性中提取returnUrl。

 public class SSOAuthorizeAttribute : AuthorizeAttribute
 {
      public override void OnAuthorization( 
                          AuthorizationContext filterContext )
      {
          if (filterContext == null)
          {
              throw new ArgumentNullException( "filterContext" );
          }

          if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
          {
              // get from cached variable from web configuration
              string loginUrl = ... 
              if (filterContext.HttpContext.Request != null)
              {
                  loginUrl += "?ReturnUrl=" + filterContext.HttpContext
                                                           .Request
                                                           .Url
                                                           .AbsoluteUri;
              }

              filterContext.Result = new RedirectResult( loginUrl );
          }
      }
 }

假设进行表单身份验证,请在服务器B应用程序web.config中,将Forms标记上的loginUrl属性设置为Controller Action方法,该方法在重定向到服务器A之前会使用绝对URL。

在服务器B上配置

<authentication mode="Forms">
  <forms loginUrl="/Account/LoginRedirect" />
</authentication>

动作方法看起来像

 public RedirectResult LoginRedirect(string returnUrl)
    {
       var requestUrl = HttpContext.Current.Request.Url;
       return LoginUrlOnServerA + 
              "?returnUrl=" +          
              HttpUtility.UrlEncode(string.Format("http://{0}:{1}{2}",
                requestUrl.Host,
                requestUrl.Port,
                HttpUtility.UrlDecode(returnUrl)));
     }

https://stackoverflow.com/a/583608/80589,但更短:

public RedirectResult LogOn(string returnUrl)
{
  var r = new Uri(Request.Url, returnUrl).ToString();
  return Redirect("https://logonserver.com/?return_url=" + Url.Encode(r));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM