ASP.NET MVC .asmxWebサービスを持つアプリケーションがあります
WebサービスのWebメソッドで使用するアクションフィルター属性を作成して、ユーザーIDとパスワードのRequestヘッダーを確認し、無効または存在しない場合は不正な応答コードをスローします。
しかし、彼らは呼ばれるようには見えません!ブレークポイントはヒットしません。
まず、[〜#〜] mvc [〜#〜]属性を使用して、[〜#〜] asmx [〜#〜]で呼び出されるWebサービスを承認するための許容可能な方法を使用します。 = Webサービス?
次に、Webサービスのメソッド呼び出しを承認するためのより良い/より効率的な方法はありますか?
最初の質問への回答として、[〜#〜] mvc [〜#〜]フィルターおよびWeb APIフィルターはによってトリガーできません[〜#〜] asmx [〜#〜] Webサービス。
アクションフィルターは[〜#〜] mvc [〜#〜]パイプラインの一部であり、コントローラー(またはAPIコントローラー)のアクションメソッドが実行される前(または実行された後)にトリガーされます。これらは[〜#〜] mvc [〜#〜]フレームワーク内でのみ使用できます。
アクションフィルターは、[〜#〜] mvc [〜#〜]コントローラー(OnActionExecuting
)の仮想メソッドをオーバーライドします。 [〜#〜] mvc [〜#〜]コントローラーだけがそのようなメソッドを持っており、[〜#〜] mvc [〜#〜]パイプラインだけがそれらをチェックします
さらに悪いことに、[〜#〜] 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>
承認用のカスタム属性フィルターを作成するのは良い考えだと思います。このように認証をカスタマイズするコスチュームフィルターを作成できます。
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つのメソッドをオーバーライドしています。
- OnAuthorisation:ここにあなたの承認ロジックがあります。ここでは不正なリクエストの処理をチェックしています。
- HandleUnauthorizedRequest:不正アクセスを処理するためのロジックがあります。不正アクセスを処理するために実行されるのは、親のクラスHandleUnauthorizedRequestを呼び出しています。
MVCおよびWebAPIパイプラインは、古いスタイルの.ASMXWebサービスと直接互換性がありません。これが、これらの属性をWebメソッドに配置したときに起動しない理由です。コードベースに応じて、コードをWeb API 2プラットフォームに変換(書き換え)できます。これは、サービスを作成するための新しい推奨方法です。これには、従来のWebサービス(.asmx)に比べて次の利点があります。
xml
とjson
です。送受信されるペイロードは通常、軽量であることは言うまでもなくはるかに単純であるため、これはクライアントにとって非常に簡単に操作できます(.asmxサービスで使用されるSOAPエンベロープは非常に肥大化しています)。すると、質問は "既存のコードを変換する必要がありますか?"になります。
私が避けたいのは、Webサービスを呼び出すラッパーをWebAPIで作成することです。
ここで、.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認証を使用できます。 C#では、クライアントは NetworkCredential クラスを使用して資格情報を渡します。基本的に、クライアントが行うことは、認証資格情報をHTTPヘッダーに適用することです。私はこれをかなり見つけました 良いSO answer HTTP呼び出しを行うときにNetworkCredentialクラスが実際に何に変換されるかについて。リクエストがメソッドに到達する前に認証と承認が行われるように、IISを構成する必要があります。また、認証用ではなく、Webメソッド(上記と同様)で直接認証用のカスタムコードを実行することもできます。
フォーム認証に関しては、上記で指定されたTraditional / defacto
の方法に勝る利点があるWebサービスでこれを行う良い方法はありません。ただし、(現在).asmxサービスを含むWebサイトのセットアップが既にある場合は、クライアントが既にサイトに対して認証されていると想定して、サービスの承認をweb.config
に含めることができます。
認証と可能な承認を処理するカスタムHttpModuleを作成することもできます。このアプローチの長所は、Webサービスのビジネスロジックを認証/承認から切り離すことです。これは両刃の剣ですが、URLを解析するモジュールと、リクエストが許可されているかどうかを確認するための目的のメソッドを維持する必要があるためです。これにより、カップリングが壊れやすくなる可能性があります。
質問の最初の部分:
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);
}
}
}