5

そのため、[Authorize] タグでいくつかのヒントを見つけましたが、問題を解決するものは何もありません。

私のシナリオは、RestSharp を使用した統合テストでヒットしたい Web Api メソッドがあるというものです。ただし、RestSharp は呼び出しの結果ではなく、ログイン ページを取得しています。

[Authorize]
public Item GetItem([FromBody] int id) 
{
   return service.GetItem(id);
}

この製品はカスタム ログイン システムを使用しており、私が本当に望んでいるのは、統合テストの場合にのみ [Authorize] バッジを無効にする方法です。ただし、匿名ユーザーを許可するとバッジが「無効」になると読んだので、ソリューションには統合テストプロジェクトがあり、そのプロジェクトには App.config ファイルがあります。私が入れたそのファイルに:

 <location>
  <system.web>
   <authorization>
     <allow users="?"/>
    </authorization>
  </system.web>
 </location>

しかし、これも機能していないようです。何が起こっているのか、なぜ機能しないのか、これを機能させるために何ができるのかについての説明をいただければ幸いです。

Thread.CurrentPrincipal を設定しようとしましたが、うまくいきませんでした (間違っていたのかもしれません。コードで「何か」を許可するように設定できますか?)。認証は、それがまったく役立つ場合、httpmodule で処理されます。

4

3 に答える 3

8

この質問は、webapi エンドポイントで RestSharp から「実際の」リクエストを発行することに関するものであるため、この提案は OP シナリオにはすぐには適用されません..しかし:

私は , and を使用してインメモリ Web Api テストを使用してHttpConfigurationHttpServerます( Badri の提案HttpMessageInvokerによく似ていると思います)。このように、メモリ内で完全なスタック (エンド ツー エンド テスト) をテストできるため、リスナーやポートを開く必要はありません。ビルド サーバーや Heroku インスタンスなどで非常に便利です。

メモリ内テストを使用して、Thread.CurrentPrincipal..を設定する方法は次のとおりです。テスト基本クラスには、次のようなヘルパーがあります。

protected void AuthentateRequest()
{
    Thread.CurrentPrincipal = new AuthenticatedPrincipal(Thread.CurrentPrincipal);
}

これを使用します:

public class AuthenticatedPrincipal : IPrincipal
{
    private readonly IPrincipal _principalToWrap;
    private readonly IIdentity _identityToWrap;

    public AuthenticatedPrincipal(IPrincipal principalToWrap)
    {
        _principalToWrap = principalToWrap;
        _identityToWrap = new AuthenticatedIdentity(principalToWrap.Identity);
    }

    public bool IsInRole(string role)
    { return _principalToWrap.IsInRole(role); }

    public IIdentity Identity
    {
        get { return _identityToWrap; }
        private set { throw new NotSupportedException(); }
    }
}

public class AuthenticatedIdentity : IIdentity
{
    private readonly IIdentity _identityToWrap;

    public AuthenticatedIdentity(IIdentity identityToWrap)
    {
        _identityToWrap = identityToWrap;
    }

    public string Name
    {
        get { return _identityToWrap.Name; }
        private set { throw new NotSupportedException(); }
    }
    public string AuthenticationType
    {
        get { return _identityToWrap.AuthenticationType; }
        private set { throw new NotSupportedException(); }
    }
    public bool IsAuthenticated
    {
        get { return true; }
        private set { throw new NotSupportedException(); }
    }
}

IPrincipal手動でスタブするのはやり過ぎのように思えるかもしれませんが、モック フレームワークを試してみたところ、一部のテスト ランナーで爆発しました (Resharper と TeamCity ですが、NCrunch ではありません - AppDomains でのシリアル化に関するものだと思います)。

これはアクション メソッドThread.CurrentPrincipal内で設定されるため、認証されていると信じ込ませます。ApiControllerAuthorizeAttribute

于 2014-12-03T02:26:11.480 に答える
5

を設定する方法は次のとおりですThread.CurrentPrincipal。このようなメッセージ ハンドラーを Web API プロジェクトに追加し、そのハンドラーをlike so:のRegisterメソッドに追加します。WebApiConfig.csconfig.MessageHandlers.Add(new MyTestHandler());

public class MyTestHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
                                 HttpRequestMessage request,
                                     CancellationToken cancellationToken)
    {
        var local = request.Properties["MS_IsLocal"] as Lazy<bool>;
        bool isLocal = local != null && local.Value;

        if (isLocal)
        {
            if (request.Headers.GetValues("X-Testing").First().Equals("true"))
            {
                var dummyPrincipal = new GenericPrincipal(
                                        new GenericIdentity("dummy", "dummy"),
                                          new[] { "myrole1" });

                Thread.CurrentPrincipal = dummyPrincipal;

                if (HttpContext.Current != null)
                    HttpContext.Current.User = dummyPrincipal;
            }
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

このハンドラーは、認証されたプリンシパルを設定して、すべてを[Authorize]満足させます。このアプローチにはリスクの要素があります。テストの目的でのみ、このハンドラーを Web API パイプラインにプラグインする必要があります。このハンドラーをプロダクション コードのパイプラインに (意図的またはその他の方法で) プラグインすると、基本的に認証メカニズムが無効になります。リスクをある程度軽減するために (API がローカルでアクセスされないことを願っています)、アクセスがローカルであることX-Testingと、値がのヘッダーがあることを確認しますtrue

RestSharp から、カスタム ヘッダーを追加します。

var request = new RestRequest(...);
request.AddHeader("X-Testing", "true");

ところで、統合テストでは、Web ホスティングではなくインメモリ ホスティングを使用したいと思います。そうすれば、Web API は同じテスト プロジェクトで実行され、運用環境で何かが壊れることを恐れることなく、Web API を使って好きなことを行うことができます。インメモリ ホスティングの詳細については、こちらこちらをご覧ください。

于 2013-08-05T03:52:50.467 に答える