prevent XmlHtt prequest重定向在.net MVC WS-联合会网站响应 [英] Prevent XmlHttpRequest redirect response in .Net MVC WS-Federation Site

查看:254
本文介绍了prevent XmlHtt prequest重定向在.net MVC WS-联合会网站响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是WS联合在一个MVC 3网站(声明式)身份验证和时遇到麻烦保持一些距离时,认证失败返回一个重定向发送JSON我的API控制器。我有一个名为API与几个控制器,只是返回JSON的领域,这些控制器都来自同一个基类继承。我想,而不是向下发送合法的401错误响应302重定向的默认情况下发生的。

I'm using WS Federated (Claims Aware) authentication on an MVC 3 site and am having trouble keeping some of my API controllers that send JSON from returning a redirect when the authentication fails. I have an Area called API with several controllers that just return JSON, these controllers all inherit from the same base class. I want to send down legitimate 401 error responses instead of 302 redirects that are happening by default.

我也跟着某些方向上,我发现了一个过滤器,我把我的API控制器动作创造演唱会定制 WSFederationAuthenticationModule

I followed some directions I found for creating a custom WSFederationAuthenticationModule in concert with a filter I put on my API controller actions:

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项目:

But my logging shows that I am never finding the IsService item in the Items:

{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 不是过滤器和模块之间是相同的,但我不知道。

I think this may be a problem with the HttpContext.Current not being the same between the filter and the module, but I'm not sure.

我试过另一种选择是订阅中的的Application_Start 事件 FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider 我的事件的global.asax.cs,但WSFederationAuthenticationModule为空当时

Another option I tried was to subscribe to the FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider event in the Application_Start event of my Global.asax.cs, but the WSFederationAuthenticationModule is null at that time.

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 事件。

推荐答案

我想我已经找到了答案这个问题,想绕回来,留在世界上任何其他人可能会遇到这样的一个答案。

I think I've found an answer to this problem and want to circle back and leave an answer for anyone else in the world that might encounter this.

我的问题是, HttpContext.Current.Items 之间的不匹配我的 ActionFilterAttribute WSFederationAuthenticationModule 所以我结束了检查的背景下,增加一些检查类似<一个href=\"http://haacked.com/archive/2011/10/04/$p$pvent-forms-authentication-login-page-redirect-when-you-donrsquot-want.aspx\">Phil Haacks窗体重定向燮preSS例

My problem was that the HttpContext.Current.Items wasn't matching up between my ActionFilterAttribute and the WSFederationAuthenticationModule so I ended up inspecting the context and adding some checks similar to Phil Haacks Forms Redirect Suppress Example

下面是我更新的自定义 WSFederationAuthenticationModule 如下:

Here is what my updated custom WSFederationAuthenticationModule looks like:

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:

And of course, you'll need to add this to your web.config in place of the default authentication module:

<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>

这篇关于prevent XmlHtt prequest重定向在.net MVC WS-联合会网站响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆