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

时间:2008-12-18 22:14:34

标签: asp.net-mvc forms-authentication

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

这是皱纹。在服务器b上使用app有两个控制器,一个是公共的,一个是安全的。如果[authorize]装饰放在公共中的动作(默认控制器)上,我会得到正确的绝对URL。但是,如果它在它自己的控制器中,我会得到一个相对的URL。

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

想法?

3 个答案:

答案 0 :(得分:15)

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

答案 1 :(得分:5)

假设表单身份验证,在服务器B apps 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)));
     }

答案 2 :(得分:0)

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