简体   繁体   English

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

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

I have a central authentication application on server a. 我在服务器a上有一个中央身份验证应用程序。 Server b has one or more applications on the same domain that need to authenticate from server a. 服务器b在同一域上具有一个或多个需要从服务器a进行身份验证的应用程序。 It's easy enough to set it up so that the server b apps redirect out to server a. 设置起来很容易,以便服务器b应用重定向到服务器a。 What's not so easy is getting the ReturnURL to be absolute. 要使ReturnURL成为绝对值不是那么容易。

Here's the wrinkle. 这是皱纹。 Consuming app on server b has two controllers, one public and one secured. 服务器b上的消费应用程序具有两个控制器,一个为公共控制器,另一个为安全控制器。 If the [authorize] decoration is placed on an action in the public (which is the default controller), I get the proper absolute URL. 如果将[authorize]装饰放在公众的某个动作上(这是默认控制器),我将获得正确的绝对URL。 However, if its in it's own controller I get a relative URL. 但是,如果它在它自己的控制器中,则会得到一个相对URL。

I can intercept the on pre-request event in the consuming applications, but I need some parts of the site to be public, not the whole smash. 我可以在使用中的应用程序中拦截请求前事件,但是我需要使网站的某些部分公开,而不是整个粉碎。

Ideas? 有想法吗?

The way the standard AuthorizeAttribute works is by setting the response status code to 401 if the request is not authenticated. 标准AuthorizeAttribute的工作方式是,如果请求未通过身份验证,则将响应状态代码设置为401。 This kicks in the default authentication module's standard response to an unauthorized request. 这将启动默认身份验证模块对未授权请求的标准响应。 I assume that you're using forms-based authentication, which would build the return url based on the url in the request. 我假设您使用的是基于表单的身份验证,该身份验证将基于请求中的URL构建返回URL。 In this case, probably a relative URL. 在这种情况下,可能是相对URL。

One thing you could do is instead of relying on the built-in behavior, you could implement a SSOAuthorizeAttribute which extends the AuthorizeAttribute class and overrides OnAuthorization. 您可以做的一件事是,不必依靠内置行为,而可以实现SSOAuthorizeAttribute,它扩展了AuthorizeAttribute类并覆盖了OnAuthorization。 You could then extract the loginUrl from the forms element in the web configuration and build your own RedirectResult and pull the returnUrl from the HttpContext.Request.Url.AbsoluteUri property in the AuthorizationContext parameter. 然后,您可以从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 );
          }
      }
 }

Assuming forms authentication, in the server B apps web.config, set the loginUrl attribute on the forms tag to a Controller Action method that tacks on the absolute url before redirecting to server A. 假设进行表单身份验证,请在服务器B应用程序web.config中,将Forms标记上的loginUrl属性设置为Controller Action方法,该方法在重定向到服务器A之前会使用绝对URL。

Config on server B 在服务器B上配置

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

The action method would look like 动作方法看起来像

 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)));
     }

as https://stackoverflow.com/a/583608/80589 but shorter: 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