2012-02-28 58 views
4

我在MVC 3站點上使用WS Federated(Claim Aware)身份驗證,並且遇到問題時仍然無法讓發送JSON的一些API控制器返回重定向認證失敗。我有一個叫做API的Area,帶有幾個只返回JSON的控制器,這些控制器都從同一個基類繼承而來。我想發送合法的401錯誤響應,而不是默認發生的302重定向。防止XmlHttpRequest在.Net MVC WS-Federation站點中重定向響應

我跟一些方向,我發現在演唱會與過濾器我把我的API控制器動作創建自定義WSFederationAuthenticationModule

public class WSFederationServiceAuthenticationModule : WSFederationAuthenticationModule 
{ 
    private static Log4NetLoggingService logger = new Log4NetLoggingService(); 

    public const string IsServiceIndicator = "ROIP.IsService"; 

    protected override void OnAuthorizationFailed(AuthorizationFailedEventArgs e) 
    { 
     base.OnAuthorizationFailed(e);    

     var isService = HttpContext.Current.Items[IsServiceIndicator]; 

     if (isService != null) 
     { 
      logger.Info("WSFedService: Found IsService"); 
      e.RedirectToIdentityProvider = false; 
     } 
     else 
     { 
      logger.Info("WSFedService: Did not find IsService"); 
     } 
    } 
} 

public class WSFederationServiceAuthAttribute : ActionFilterAttribute 
{ 
    private static Log4NetLoggingService logger = new Log4NetLoggingService(); 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     // Set an item that indicates this is a service request, do not redirect. 
     logger.Info("WSFedService: Setting IsService"); 
     HttpContext.Current.Items[WSFederationServiceAuthenticationModule.IsServiceIndicator] = 1; 
    } 
} 

但我的記錄顯示,我從來沒有發現在項目IsService項目:

{INFO}02/29 03:39:21 - WSFedService: Setting IsService 
{INFO}02/29 03:39:32 - WSFedService: Setting IsService 
{INFO}02/29 03:39:32 - WSFedService: Setting IsService 
{INFO}02/29 03:50:39 - WSFedService: Did not find IsService 
{INFO}02/29 03:53:16 - WSFedService: Did not find IsService 
{INFO}02/29 03:53:29 - WSFedService: Did not find IsService 

我想這可能是與HttpContext.Current不是過濾器和模塊之間的相同問題,但我不知道。

我試過的另一個選擇是在我的Global.asax.cs的Application_Start事件中訂閱FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider事件,但WSFederationAuthenticationModule當時爲空。

private void ConfigureWSFederationAuthentication() 
{ 
    bool hasFederatedAuthentication = false; 
    try 
    { 
     if (FederatedAuthentication.WSFederationAuthenticationModule != null) 
     { 
      hasFederatedAuthentication = true; 
     } 
    } 
    catch 
    { 
     hasFederatedAuthentication = false; 
    } 

    if (hasFederatedAuthentication) 
    { 
     Logger.Info("WSFederation: Registering for Event Handler"); 
     FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider += (s, e) => 
      { 
       var msg = string.Empty; 
       try 
       { 
        if (HttpContext.Current.Request.Headers["X-Requested-With"] == "XMLHttpRequest") 
        { 
         e.Cancel = true; 
         msg = "Found XMLHttpRequest header"; 
        } 
        else 
        { 
         msg = "Did not find XMLHttpRequest header"; 
        } 
       } 
       catch (Exception ex) 
       { 
        msg = "WSFederation: Event Handler Error: " + ex.Message; 
       } 

       Logger.Info("WSFederation: Redirecting from Event Handler: " + msg); 
      }; 
    } 
    else 
    { 
     Logger.Info("WSFederation: Null WSFederationAuthenticationModule"); 
    } 
} 

我想知道無論是如何獲得的第一個選項工作,或者我應該訂閱RedirectingToIdentityProvider事件。

回答

7

我想我已經找到了這個問題的答案,並且希望迴圈併爲世界上任何可能遇到此問題的人留下一個答案。

我的問題是,HttpContext.Current.Items沒有之間的匹配我的ActionFilterAttributeWSFederationAuthenticationModule所以我結束了檢查的背景和添加類似於Phil Haacks Forms Redirect Suppress Example

這裏進行一些檢查是我更新的自定義WSFederationAuthenticationModule樣子:

public class WSFederationServiceAuthenticationModule : WSFederationAuthenticationModule 
{ 
    private static Log4NetLoggingService logger = new Log4NetLoggingService(); 

    protected override void OnAuthorizationFailed(AuthorizationFailedEventArgs e) 
    { 
     base.OnAuthorizationFailed(e);    

     var context = HttpContext.Current; 
     var req = context.Request; 
     var resp = context.Response; 

     if (req == null || resp == null) 
     { 
      logger.Info("WSFedService: Did not find Request or Response"); 
      return; 
     } 

     if ((resp.StatusCode == 302 || resp.StatusCode == 401) && req.Headers["X-Requested-With"] == "XMLHttpRequest") 
     { 
      logger.Info("WSFedService: Found Redirect and Header"); 
      e.RedirectToIdentityProvider = false; 
     } 
     else 
     { 
      logger.Info(string.Format("WSFedService: Did not find redirect status code or XMLHttpRequest Header: {0}", resp.StatusCode)); 
     } 

    } 
} 

當然,你需要在這個地方的默認身份驗證模塊添加到您的web.config:

<system.web> 
    <httpModules> 
     <!-- Old and Busted... 
     <add name="WSFederationAuthenticationModule" 
      type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 
     --> 

     <!-- New Hotness... --> 
     <add name="WSFederationAuthenticationModule" 
      type="MyApp.Web.Authentication.WSFederationServiceAuthenticationModule, MyApp.Web" /> 
    </httpModules> 
</system.web> 

<system.webServer> 
    <modules> 
     <!-- Old and Busted... 
     <add name="WSFederationAuthenticationModule" 
      type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
      preCondition="managedHandler"/> 
     --> 

     <!-- New Hotness... --> 
     <add name="WSFederationAuthenticationModule" 
      type="MyApp.Web.Authentication.WSFederationServiceAuthenticationModule, MyApp.Web" 
      preCondition="managedHandler"/> 

    </modules> 
</system.webServer> 
+0

最後!感謝+1) – cleftheris 2012-05-25 13:36:52

2

我意識到這個線程是古老的,但我試圖解決同樣的問題時遇到它(我有網絡apis,我想與活動客戶端一起使用,並且我想發送一個401如果認證向南)

..而且,根據您的情況,處理Global.asax中的授權失敗事件可能會更容易/更少,並在那裏進行檢查。

這個環節是我一直在下面:http://msdn.microsoft.com/en-us/library/system.identitymodel.services.wsfederationauthenticationmodule.authorizationfailed.aspx

..和它看起來非常簡單。

+0

我已經完成了相同事件的使用和事​​件處理程序。奇蹟般有效! – Raybiez 2013-04-09 07:23:10