11

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

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

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

想法?

4

3 回答 3

16

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

您可以做的一件事是,您可以实现一个扩展 AuthorizeAttribute 类并覆盖 OnAuthorization 的 SSOAuthorizeAttribute,而不是依赖内置行为。然后,您可以从 Web 配置中的表单元素中提取 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 );
          }
      }
 }
于 2008-12-18T22:43:26.847 回答
5

假设表单身份验证,在服务器 B 应用程序 web.config 中,将表单标记上的 loginUrl 属性设置为控制器操作方法,该方法在重定向到服务器 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)));
     }
于 2009-02-24T21:05:54.647 回答
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));
}
于 2012-06-04T09:23:37.267 回答