6

MVC 3 サイトで WS Federated (Claims Aware) 認証を使用していますが、JSON を送信する一部の API コントローラーが認証に失敗したときにリダイレクトを返さないようにするのに問題があります。JSON を返すだけのいくつかのコントローラーを備えた API と呼ばれるエリアがあり、これらのコントローラーはすべて同じ基本クラスから継承されます。デフォルトで発生する 302 リダイレクトの代わりに、正当な 401 エラー応答を送信したいと考えています。

WSFederationAuthenticationModuleAPIコントローラーアクションに適用したフィルターと連携してカスタムを作成するために見つけたいくつかの指示に従いました。

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.csFederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProviderのイベントでイベントをサブスクライブすることでしたApplication_Startが、その時点で WSFederationAuthenticationModule は null です。

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最初のオプションを機能させる方法、またはイベントを購読する場所を知りたいです。

4

3 に答える 3

9

私はこの問題に対する答えを見つけたと思います。これに遭遇する可能性のある世界中の誰かのために、円を返して答えを残したいと思います。

私の問題は、が私と のHttpContext.Current.Items間で一致していなかったため、最終的にコンテキストを調べて、 Phil Haacks Forms Redirect Suppress Exampleと同様のチェックを追加することになりましたActionFilterAttributeWSFederationAuthenticationModule

更新されたカスタム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>
于 2012-03-07T19:22:26.410 に答える
3

このスレッドは古くからあることに気づきましたが、同じ問題を解決しようとしているときに遭遇しました(アクティブなクライアントで使用したいWeb APIがあり、認証がリダイレクトではなく南に進んだ場合は401を送信したいと思います)。

..また、状況によっては、Global.asaxで承認失敗イベントを処理し、そこでチェックを行う方が簡単/関与が少ない場合があります。

このリンクは私がフォローしているものです:http://msdn.microsoft.com/en-us/library/system.identitymodel.services.wsfederationauthenticationmodule.authorizationfailed.aspx

..そしてそれは簡単なようです。

于 2012-10-29T21:50:32.790 に答える
1

私の場合、JWT認証を使用して保護されたWebサイトのパス「/ api」の下にAPIをホストしました。

この問題を修正するために、次のオーバーライドが WSFederationAuthenticationModule で行われました (もちろん、このカスタム モジュールを web.config のSystem.WebServerに登録してください)。

public class CustomWSFederationAuthenticationModule : System.IdentityModel.Services.WSFederationAuthenticationModule
{
    protected override void OnAuthorizationFailed(AuthorizationFailedEventArgs e)
    {
        if (!IsApiCall())
            e.RedirectToIdentityProvider = false;
        base.OnAuthorizationFailed(e);
    }

    protected override void OnEndRequest(object sender, EventArgs args)
    {
        if (!IsApiCall())
            base.OnEndRequest(sender, args);
    }

    private bool IsApiCall()
    {
        return (HttpContext.Current.Request.Path.ToLowerInvariant().Contains("/api/"));
    }
}
于 2018-04-20T12:50:24.813 に答える