11

ASP.NETでは、FormsAuthenticationModuleはHTTP 401をインターセプトし、ログインページにHTTP302リダイレクトを返します。jsonを要求してhtmlでログインページを取得するため、これはAJAXにとって苦痛ですが、ステータスコードはHTTP200です。

ASP.NET Web APIでこの傍受を回避する方法は何ですか?

ASP.NET MVC4では、接続を明示的に終了することで、この傍受を非常に簡単に防ぐことができます。

public class MyMvcAuthFilter:AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest() && !filterContext.IsChildAction)
        {
            filterContext.Result = new HttpStatusCodeResult(401);
            filterContext.HttpContext.Response.StatusCode = 401;
            filterContext.HttpContext.Response.SuppressContent = true;
            filterContext.HttpContext.Response.End();
        }
        else
            base.HandleUnauthorizedRequest(filterContext);
    }
}

ただし、ASP.NET Web APIでは接続を明示的に終了できないため、このコードを使用しても、FormsAuthenticationModuleは応答をインターセプトし、ログインページにリダイレクトを送信します。

public class MyWebApiAuth: AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if(actionContext.Request.Headers.Any(h=>h.Key.Equals("X-Requested-With",StringComparison.OrdinalIgnoreCase)))
        {
            var xhr = actionContext.Request.Headers.Single(h => h.Key.Equals("X-Requested-With", StringComparison.OrdinalIgnoreCase)).Value.First();

            if (xhr.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase))
            {
                // this does not work either
                //throw new HttpResponseException(HttpStatusCode.Unauthorized);

                actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
                return;
            }
        }

        base.HandleUnauthorizedRequest(actionContext);
    }
}

ASP.NET Web APIでこの動作を回避する方法は何ですか?私は調べていましたが、それを行う方法を見つけることができませんでした。

よろしく。

PS:これが2012年であり、この問題がまだ続いているとは信じられません。

4

3 に答える 3

5

誰かがAuthorize属性を使用してASP.NETMVCアプリで同じ問題に対処することに興味がある場合:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class Authorize2Attribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new HttpStatusCodeResult((int) HttpStatusCode.Forbidden);
        }
        else
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
            }
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
} 

このようにして、ブラウザは禁止されたリクエストと許可されていないリクエストを適切に区別します。

于 2013-07-06T06:08:02.637 に答える
4

MVC 4 RCのリリースノートは、これがベータ版以降に解決されたことを示しています-どちらを使用していますか?

http://www.asp.net/whitepapers/mvc4-release-notes ASP.NET Web APIによって処理される未承認の要求は401を返します未承認:ASP.NET Web APIによって処理される未承認の要求は、リダイレクトする代わりに標準の401未承認の応答を返すようになりました応答をAjaxクライアントで処理できるように、ユーザーエージェントをログインフォームに追加します。

MVCのソースコードを調べると、SuppressFormsAuthRedirectModule.csを介して追加された機能があるようです。

http://aspnetwebstack.codeplex.com/SourceControl/network/forks/BradWilson/AspNetWebStack/changeset/changes/ae1164a2e339#src%2fSystem.Web.Http.WebHost%2fHttpControllerHandler.cs

    internal static bool GetEnabled(NameValueCollection appSettings)
    {
            // anything but "false" will return true, which is the default behavior

したがって、これはデフォルトで有効になっているようで、RCはヒロイックなしで問題を修正するはずです...副次的な点として、AppSettingshttp://d.hatena.ne.jp/shiba-を使用してこの新しいモジュールを無効にできるようです。 yan / 20120430/1335787815

<appSettings> 
    <Add Key = "webapi:EnableSuppressRedirect"  value = "false" /> 
</appSettings>

編集(例と説明)

これで、 GitHubでこのアプローチの例を作成しました。新しいリダイレクト抑制では、2つの正しい「承認」属性を使用する必要があります。MVCWeb[System.Web.Mvc.Authorize]およびWebAPI[System.Web.Http.Authorize]は、コントローラーおよび/またはグローバルフィルターリンクにあります。

ただし、この例では、アプローチの制限があります。web.configの「承認」ノードは常にMVCルートよりも優先されるようです。たとえば、このような構成はルールを上書きし、ログインにリダイレクトします。

<system.web>
    <authentication mode="Forms">
    </authentication>
    <authorization>
        <deny users="?"/> //will deny anonymous users to all routes including WebApi
    </authorization>
</system.web> 

残念ながら、Location要素を使用して一部のURLルートに対してこれを開くと、機能していないように見え、WebApi呼び出しは引き続き傍受され、ログインにリダイレクトされます。

ソリューション

MVCアプリケーションの場合は、Web.Configから構成を削除し、コード内のグローバルフィルターと属性を使用することをお勧めします。

Web.Config for MVCで認証ノードを使用する必要がある場合、またはハイブリッドASP.NETとWebApiアプリケーションを使用する必要がある場合は、@ PilotBob(以下のコメント)で、サブフォルダーと複数のWeb.Configを使用してケーキとそれを食べる。

于 2012-06-19T10:56:30.990 に答える
3

次のプロパティを設定することで、web.configの匿名拒否設定を回避することができました。

Request.RequestContext.HttpContext.SkipAuthorization = true;

これは、Global.asax.csのApplication_BeginRequestメソッドのRequestオブジェクト(RawURLプロパティやその他のヘッダー情報など)をチェックして、匿名アクセスを許可する領域にリクエストがアクセスしていることを確認した後に行います。APIアクションが呼び出された後も、認証/承認を実行します。

于 2013-01-24T19:56:59.480 に答える