web-dev-qa-db-ja.com

MVC4プロジェクトからASMX.NETWebサービスを承認する正しい方法

ASP.NET MVC .asmxWebサービスを持つアプリケーションがあります

WebサービスのWebメソッドで使用するアクションフィルター属性を作成して、ユーザーIDとパスワードのRequestヘッダーを確認し、無効または存在しない場合は不正な応答コードをスローします。

しかし、彼らは呼ばれるようには見えません!ブレークポイントはヒットしません。

まず、[〜#〜] mvc [〜#〜]属性を使用して、[〜#〜] asmx [〜#〜]で呼び出されるWebサービスを承認するための許容可能な方法を使用します。 = Webサービス?

次に、Webサービスのメソッド呼び出しを承認するためのより良い/より効率的な方法はありますか?

10
Jimbo

最初の質問への回答として、[〜#〜] mvc [〜#〜]フィルターおよびWeb APIフィルターはによってトリガーできません[〜#〜] asmx [〜#〜] Webサービス

  1. アクションフィルターは[〜#〜] mvc [〜#〜]パイプラインの一部であり、コントローラー(またはAPIコントローラー)のアクションメソッドが実行される前(または実行された後)にトリガーされます。これらは[〜#〜] mvc [〜#〜]フレームワーク内でのみ使用できます。

    アクションフィルターは、[〜#〜] mvc [〜#〜]コントローラー(OnActionExecuting)の仮想メソッドをオーバーライドします。 [〜#〜] mvc [〜#〜]コントローラーだけがそのようなメソッドを持っており、[〜#〜] mvc [〜#〜]パイプラインだけがそれらをチェックします

  2. さらに悪いことに、[〜#〜] asmx [〜#〜]サービスは、デフォルトでは、[〜#〜] soap [〜#〜]プロトコルではなく使用します[〜#〜] http [〜#〜]プロトコル。 [〜#〜] soap [〜#〜]サービスはHTTPコンテキスト(例:HttpContext.Current.User)または[〜#〜] http [〜#〜]にアクセスできませんフレームワーク。

    Webサービスは、HTTPプロトコルを使用するように構成できます。しかし、それでも[〜#〜] mvc [〜#〜]特定の属性は役に立ちません。


レガシーを認証する方法[〜#〜] asmx [〜#〜]サービス

  • 理想的な方法は、 サービス参照を追加 プロジェクトにMVC 4プロジェクトを呼び出し、[〜#〜] asmx [〜#〜]メソッドを次のように呼び出すことです。 [Authorize]で保護されたアクションメソッドまたはWeb APIメソッドのクラスライブラリメソッド。

    このようにして、[〜#〜] mvc [〜#〜]またはWeb API認証フィルターを活用できます。

  • [〜#〜] asmx [〜#〜]サービスを直接保護する場合は、[〜#〜を構成することで、フォーム認証を使用してHttpContext.Current.Userに確認できます。 ] asmx [〜#〜]使用するサービス[〜#〜] http [〜#〜]プロトコル。

web.configで

<location path="SecuredMethod.asmx">
  <system.web>
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
  </system.web>
</location> 
7
Dave Alperovich

承認用のカスタム属性フィルターを作成するのは良い考えだと思います。このように認証をカスタマイズするコスチュームフィルターを作成できます。

namespace CustomeFilters
{
    class CustomAuthorize : AuthorizeAttribute
    {
        private const string _securityParameter = "someCredentials"; // Name of the url parameter. 
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (Authorize(filterContext))
            {
                return;
            }

            HandleUnauthorizedRequest(filterContext);
        }


    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        //Your logic for unauthorized access
        HttpRequestBase request = filterContext.RequestContext.HttpContext.Request;
        string deviceId = request.Params[_securityParameter]; //Your may have values in request headers

        if (!string.IsNullOrEmpty(_securityParameter ))
        {
            base.HandleUnauthorizedRequest(filterContext);

        }

        //You can also check if request is authorized as basic authentication or not
        //if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
    }


    private bool Authorize(AuthorizationContext actionContext)
    {
            HttpRequestBase request = actionContext.RequestContext.HttpContext.Request;

            // Your authorisation logic goes here..                                     

           //actionContext.RequestContext.HttpContext.Response.StatusCode = 400;

           //actionContext.Result = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = "Request from invalid device !" };

            bool success = <true/false>;//Acording to authorisation logic
            return success;
    }
}

このように使用されます

    [CustomAuthorize]
    public ActionResult Test()
    { 
        ViewBag.Message = "Hello World.";

        return View();
    }

ここでは、MVC認証からAuthorize属性を継承しています。これは2つのメソッドをオーバーライドしています。

  1. OnAuthorisation:ここにあなたの承認ロジックがあります。ここでは不正なリクエストの処理をチェックしています。
  2. HandleUnauthorizedRequest:不正アクセスを処理するためのロジックがあります。不正アクセスを処理するために実行されるのは、親のクラスHandleUnauthorizedRequestを呼び出しています。
2
Pranav Labhe

.ASMXサービスとAuthorizeAttribute

MVCおよびWebAPIパイプラインは、古いスタイルの.ASMXWebサービスと直接互換性がありません。これが、これらの属性をWebメソッドに配置したときに起動しない理由です。コードベースに応じて、コードをWeb API 2プラットフォームに変換(書き換え)できます。これは、サービスを作成するための新しい推奨方法です。これには、従来のWebサービス(.asmx)に比べて次の利点があります。

  1. データ形式-クライアントは、受信するデータの形式を決定できます。現在サポートされている2つの形式は、xmljsonです。送受信されるペイロードは通常、軽量であることは言うまでもなくはるかに単純であるため、これはクライアントにとって非常に簡単に操作できます(.asmxサービスで使用されるSOAPエンベロープは非常に肥大化しています)。
  2. アクションフィルター-Authorize属性とカスタムアクションフィルターを利用して、一般的なアクションの前処理と後処理を実行できます。
  3. HTTP動詞の意図-アクションはSOAPではなくHTTPに基づいて作成されます。 httpメソッドを利用して、公開されているWebメソッド(GET、POST、PUT、DELETE)に直接的な意味を与えることができます。
  4. 開発プラットフォーム間での使いやすさ-他のすべての条件が同じであれば、ペイロードと応答があるため、ASMXメソッドよりもWebAPIメソッドに対して作成する方がはるかに簡単です。膨満感がないため、翻訳が簡単です。 null許容型や.netDateTimeインスタンスなど、通常はWSDL定義言語に含まれている標準型の中には、翻訳が簡単なものもあります。

すると、質問は "既存のコードを変換する必要がありますか?"になります。

  • コードベースをすでに呼び出している既存のクライアントがあり、これも変換する必要がありますか?これらのクライアントが制御できない場合(たとえば、これらの呼び出し元クライアントが顧客によって作成された場合)、これが不可能になる可能性があります。
  • すでに作成したメソッドのサイズまたは数。プロジェクトを始めたばかりの場合でも、Web Apiに変換するのは簡単かもしれませんが、単体テストを備えた実質的なコードベースがすでにある場合、これは費用効果が高くない可能性があります。
  • コードに関して外部との契約がすでに定義されている場合。 WSDLで定義を作成し、そのコントラクトに基づいてクライアント開発とサーバー側開発を同時に実行することができます。その場合、クライアント側の開発者/当事者にWebAPIに変換するよう説得する必要があります。契約しますが、これは不可能な場合があります。

私が避けたいのは、Webサービスを呼び出すラッパーをWebAPIで作成することです。

  • 呼び出しの間に(別のネットワーク境界を越えて)物理層を追加し、メッセージの送信と応答の受信の遅延を増やします
  • それはあなたが作成して維持しなければならないコードの別の層を追加します
  • このような追加の(不要な)レイヤーも、変更を実装する必要があるときに不注意で欠陥を導入するのを非常に簡単にします

.ASMX認証

ここで、.ASMX Webサービスを続行し、質問How can you execute Authorization on a web serviceに対処するとします。

伝統的/事実上の

認証の従来の方法は、認証情報をSOAPヘッダーに含めることです。これは、既存のSoapHeaderAttributeを使用して簡単に実行できます。

  • SoapHeaderAttributeをWebメソッドに配置します
  • 認証に使用される渡された引数を含む認証オブジェクトを作成します
  • 認証方法を書く

私は、他のサービスが継承する抽象的な基本サービスを作成することを好みます。これにより、重複するコードが少し少なくなります。これは、認証の詳細がない完全な例です。この例では、従来のユーザー名とパスワードを使用していますが、実際には何でもかまいません(トークン、パスワードハッシュ、HMAC情報など)。これは質問の範囲外なので、認証の詳細については説明しません。

using System.Web.Services;
using System.Web.Services.Protocols;

public abstract class AuthorizedWebService : System.Web.Services.WebService 
{
    // authentication info
    public Authentication Authentication { get; set; }
    // execute the actual authentication and authorization check
    protected virtual void Authorize()
    {
        // check the Authentication instance object (passed in credentials)
        // if not authenticate or authorized
        // throw new System.Security.Authentication.AuthenticationException();
    }
}
// authentication info
public class Authentication : SoapHeader
{
    public string Username { get; set; }
    public string Password { get; set; }
}

[WebService(Namespace = "http://tempuri.org/")]
public class MyTraditionalWebService : AuthorizedWebService
{

    [WebMethod(Description = "Some web method.")]
    [SoapHeader("Authentication")]
    public string HelloWorld()
    {
        base.Authorize();
        return "Hello " + base.Authentication.Username;
    }
}

ActiveDirectory認証

ActiveDirectory認証を使用できます。 C#では、クライアントは NetworkCredential クラスを使用して資格情報を渡します。基本的に、クライアントが行うことは、認証資格情報をHTTPヘッダーに適用することです。私はこれをかなり見つけました 良いSO answer HTTP呼び出しを行うときにNetworkCredentialクラスが実際に何に変換されるかについて。リクエストがメソッドに到達する前に認証と承認が行われるように、IISを構成する必要があります。また、認証用ではなく、Webメソッド(上記と同様)で直接認証用のカスタムコードを実行することもできます。

フォーム認証

フォーム認証に関しては、上記で指定されたTraditional / defactoの方法に勝る利点があるWebサービスでこれを行う良い方法はありません。ただし、(現在).asmxサービスを含むWebサイトのセットアップが既にある場合は、クライアントが既にサイトに対して認証されていると想定して、サービスの承認をweb.configに含めることができます。

カスタムHttpModule

認証と可能な承認を処理するカスタムHttpModuleを作成することもできます。このアプローチの長所は、Webサービスのビジネスロジックを認証/承認から切り離すことです。これは両刃の剣ですが、URLを解析するモジュールと、リクエストが許可されているかどうかを確認するための目的のメソッドを維持する必要があるためです。これにより、カップリングが壊れやすくなる可能性があります。

2
Igor

質問の最初の部分:

mVC属性を使用して、ASMX Webサービスで呼び出されるWebサービスを承認するための許容可能な方法はありますか?

@DaveAlperovichによる

MVCフィルターとWeb APIフィルターは、ASMX Webサービスによってトリガーできません。

しかし、これからSO答え

ASMXはASP.NETパイプラインによるサーバーでもあるため、HttpModulesを使用するだけで、出入りを細かく制御できます。

参照と例を次に示します。 http://msdn.Microsoft.com/en-us/library/aa719858%28VS.71%29.aspx

非常に「MVCのような」ものにしたい場合は、[承認]などの属性についてWebサービスをチェックするカスタムhttpモジュールを作成します。ASP.NETMVCはオープンソースであるため、その一部を属性などをチェックする方法を参照し、それをHTTPModuleに組み込みます。

SO質問 へのリンク

それでも、最初の質問に関して文書化された公式の文書を見つけることができませんでした。それでも、MVC属性の使用中に特定のイベントがWebサービスに対して発生しない

更新

ASMXに来ている間( ソース

メッセージ形式にXMLInformation Setを使用し、メッセージのネゴシエーションと送信にアプリケーション層プロトコル、特にHypertext Transfer Protocol(HTTP)またはSimple Mail Transfer Protocol(SMTP)に依存します。

From Scott Hanselman Blog リクエストはデフォルトではASP.NETMVCルーティングメカニズムによって処理されません

ASP.NET MVCがリクエストを取得しないのはなぜですか? 2つの理由。まず、RouteExistingFilesと呼ばれるRouteCollectionのオプションがあります。デフォルトではfalseに設定されているため、ファイルがディスク上に存在する場合、ASP.NETMVCはルーティングを自動的にスキップします。

第2四半期:

webサービスのメソッド呼び出しを承認するためのより良い/より効率的な方法はありますか?

SOAPヘッダーで送信された資格情報を使用して、Webサービスを承認できます

次に例を示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace AuthExample
{

    public class Authentication : SoapHeader
    {
        public string User;
        public string Password;
    }

    /// <summary>
    /// Summary description for webrusterapi
    /// </summary>
    [WebService(Namespace = "http://xxxx.xxx")]
    [WebServiceBinding(ConformsTo = Profiles.BProfile1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class Webrusterapi: System.Web.Services.WebService
    {
        public Authentication authHeader;

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }

        [WebMethod]
        [SoapHeader("authHeader")]
        public string HelloWorldWithCredentials()
        {
            if (authHeader.User != "Foouser" & authHeader.Password != "barPassword")
            {
                new SoapException("Fault occurred", SoapException.ClientFaultCode);
            }
            return string.Format("Hello {0}", authHeader.User);
        }
    }
}
2
Webruster