ASP.NET Web APIの安全配管
28551 ワード
本編体験ASP.NET Web APIのセキュリティパイプ.ここでの安全配管とは、IIS、HttpModule、OWIN、WebAPIなど、要求および応答中に経験される各コンポーネントまたはプロセスを指す.このパイプラインでは、検証フェーズとライセンスフェーズの2つのフェーズに大別されます.ASP.NET Web API v 1バージョンの場合、セキュリティパイプは大体こうなります:→Authentication、IIS中のHttpModule→Authenticatinへのリクエスト、APIのHttpMessageHandler→Authorizationへのリクエスト、Authorization Filter→Authorizationへのリクエスト、ControlにASP.NET Web APIがv 2バージョンに来たとき、セキュリティパイプは大体:→ホスト内のOWINコンポーネントへの要求→MessageHandlerへの要求、グローバルまたは各要求→Authentication Filterへの要求→Authorization Filterへの要求が表示され、OWINコンポーネントが追加され、OWINはオープンソースであり、Microsoftはこれに基づいてKatana検証ミドルウェアを発行した.ASP.NET Web APIのホストには2つの方式がある:1、Webホスト、ASP.NET,IIS 2,自宿主,WCF,NETプロセスがOWINを考慮すると、1、IIS→ASP.NET+OWIN Bridge→ OWIN→Web API + OWIN Adapter2、Process/Host+OWIN Bridge→OWIN→Web API + OWIN Adapter
一、パイプ内の各部品を理解する
1.1 OWINミドルウェア
public class AuthenticationMiddleware
{
private readonly Func<IDictionary<string, object>, Task> _next;
public AuthenticationMiddleware(Func<IDictionary<string, object>, Task> next)
{
_next = next;
}
public async Task Invoke(IDictionary<string, object> env)
{
// env ,
env["server.user"] = CreatePrincipal();// principal;
await _next(env);
}
}
OWINミドルウェアの大まかな動作原理は,要求中のHeader,Body,ルーティングなどの情報がIDictionary
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticaitonOptions{
AuthenticationType = "Cookies",
//more
});
app.UseGoogleAuthentication(new GoogleAuthenticationOptions{
AuthenticationType = "Google";
//more
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions{
AuthenticationType = "Bearer";
// more
})
}
}
以上、少なくともOWINコンポーネントに対して検証方式を選択できることが分かる.1.3 Message Handlerは、グローバルまたはリクエストに実装されます.次のようになります.
public class MyHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//
var response = await base.SendAsync(request, cancellationToken);
//
return response;
}
}
Message HandlerはASP.からNET WEB API 2以降は存在しない.
1.4 Authentication Filter検証フィルタはグローバルに構成できる:WebApiConfig.csconfig.Filters.Add(new HostAuthenticationFilter("Bearer"));もちろん、フィルタはコントローラと方法の面に置くこともできます.
[HostAuthentication("Bearer")]
public class TestController : ApiController
{
[HostAuthentication("Google")]
public HttpResponseMessage Get(){}
[OverrideAuthentication]
[HostAuthentication("Cookies")]
public HttpResponseMessage Delete(){}
}
1.5 Authorization Filterライセンスフィルタ
[Authorize]
public class DataController : ApiController
{
[AllowAnonymous]
public Data Get(){}
[Authorize(Role = "Foo")]
public HttpResponseMessage Delete(int id){}
}
認証に失敗した場合は、401エラーを返します.1.6ユーザのIdentityを取得ApiControllerのUser属性からユーザのIdentityを取得する.Userプロパティの値はnullの場合があります.
二、例を通して安全配管を体験する
2.1 HttpModuleをカスタマイズするには、まず、要求が来たら、必ずHttpModuleを通過します.現在のユーザー情報を印刷するには、HttpModuleをカスタマイズする必要があります.
namespace SecurityPipeline
{
public class HttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
void context_BeginRequest(object sender, EventArgs e)
{
Helper.Write("HttpModule", HttpContext.Current)
}
public void Dispose()
{
}
}
}
namespace SecurityPiepeline
{
public static class Helper
{
public static void Write(string state, IPrincipal principal)
{
Debug.WriteLine("------------" + stage + "--------");
if(principal == null || principal.Identity == null || !principal.Identity.IsAuthenticated)
{
Debug.WriteLine("anonymous user");
}
else
{
Debug.WriteLine("User:" + principal.Identity.User);
}
Debug.WriteLine("
");
}
}
}
HttpContext.CurrentはIPrincipalタイプです.それからこれはWebプロジェクトで、HTTP moduleを登録する必要があります.
<configuration>
<system.webServer>
<modules>
<add name="DemoModule" type="SecurityPipeline.HttpModule"/>
</modules>
</system.webServer>
</configuration>
プロジェクトの下にdefaultがある場合.htmlページでは、プロジェクトを実行し、defaultを表示します.htmlの場合、コンソールには次のような情報が印刷されます.--HttpModule--------anonymouseは明らかに、リクエストが来て、カスタマイズされたHttp Moduleが機能しましたが、IPrincipalからUser情報を取得することはできません.2.2 ASPをインストールする.NET Web API 22.3コントローラの作成
using System.Net.Http;
public class TestController : ApiController
{
public IHttpActionResult Get()
{
Helper.Write("Controller", User);
//
//Helper.Write("Controller",Request.GetRequestContext().Principal);
return Ok();
}
}
以上、ApiControllerのUser属性でIPincipalタイプを取得しました.2.4 Microsoftをインストールする.Owin.Host.SystemWeb2.5 Microsoftをインストールします.ASP.NET Web API 2.1 OWIN2.6 Startupクラスの作成
using OWin;
using System.Web.Http;
namespace SecurityPopeline
{
public class Startup
{
public void Configuraiton()
{
var configuration = new HttpConfiguration();
configuration.Routes.MapHttpRoute("default", "api/{controller}");
}
}
}
ここで、WEB APIのHttpConfiguratonインスタンスにクラスOWINのIAppBuilderのUseWebApiメソッドを付与させる.2.7要求ルーティング:localhsot:8000/api/test表示------HttpModule------anonymous user------Controller------anonymous userは、パイプ内のHttpModuleとControllerを経由するように要求されているが、依然としてユーザー情報は取得されていない.2.8 TestMiddlewareクラスを作成してHttpModuleに入った後、Controllerに入る前に、ここはOWINコンポーネントの生存地です.
using Microsoft.Owin;
namespace SecurityPopeline.Pipeline
{
public class TestMiddleware
{
private Func<IDictionary<string, object>, Task> _next;
public TestMiddleware(Func<IDictionary<string, object>, Task> next)
{
_next = next;
}
public async Task Invoke(IDictionary<string, object> env)
{
var context = new OwinContext(env);
Helper.Write("Middleware", context.Request.User);
await _next(env);
}
}
}
2.9 StartupクラスにTestMiddlewareセクションを追加
using OWin;
using System.Web.Http;
namespace SecurityPopeline
{
public class Startup
{
public void Configuraiton(IAppBuilder app)
{
var configuration = new HttpConfiguration();
configuration.Routes.MapHttpRoute("default", "api/{controller}");
app.Use(typeo(TestMiddleware));
app.UseWebApi(configuration);
}
}
}
3.10要求ルーティング:localhsot:8000/api/test表示------HttpModule------anonymous user------Middleware------anonymous user------Controller------anonymous user表示され、要求が通るとパイプの中のHttomodule,OWINを経て、最後にControllerに到着し、ユーザー情報を取得できなかった.3.11 TestAuthenticationFilterAttributeクラスをOWINとControllerの間に追加し、認証インタフェースもあります.これも安全配管の重要な一環です.
using System.Web.Http.Filters;
using System.Threading.Tasks;
namespace SecurityPipeline.Pipeline
{
public class TestAuthenticationFilterAttribute : Attribute, IAuthenticationFilter
{
public async Task AuthenticateAsync(HttpAuthenticationContext context)
{
Helper.Write("AuthenticationFilter", context.ActionContext.RequestContext.Principal, CancellationToken..)
}
public async Task ChallengeAsync(HttpAuthenticationContext context, CancellationToken..)
{
}
public bool AllowMultiple
{
get {
return false;
}
}
}
}
コントローラフィルタ特性の追加
using System.Net.Http;
[TestAuthenticationFilter]
public class TestController : ApiController
{
public IHttpActionResult Get()
{
Helper.Write("Controller", User);
//
//Helper.Write("Controller",Request.GetRequestContext().Principal);
return Ok();
}
}
3.12要求ルート:localhsot:8000/api/test表示------HttpModule------anonymous user------Middleware------anonymous user------AuthenticationFilter------anonymous user------Controller------anonymous userが見え、経路安全配管中のHttpModule,OWINを要求し、検証したが、依然としてユーザー情報を取得していない.3.13 TestAuthorizationFilterAttrbuteクラスを追加すると、認証されたプロパティと、ControllerまたはActionに入る前に、セキュリティパイプにはもう一つの重要なメンバーがいます.
public class TestAuthorizationFilterAttribute : AuthorizeAttibute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
Helper.Write("AuthorizationFilter", actionContext.RequestContext.Prioncipal);
return base.IsAuthorized(actionContext);
}
}
コントローラのライセンス機能の追加
using System.Net.Http;
[TestAuthenticationFilter]
[TestAuthorizationFilter]
public class TestController : ApiController
{
public IHttpActionResult Get()
{
Helper.Write("Controller", User);
//
//Helper.Write("Controller",Request.GetRequestContext().Principal);
return Ok();
}
}
3.14要求ルート:localhsot:8000/api/test表示------HttpModule------anonymous user------Middleware------anonymous user------AuthenticationFilter------anonymous user------AuthorizationFilter------anonymous userそしてエラー:Authorization has been denied for this requestは、リクエストがControllerに到着する前からエラーを報告していることがわかる.そこで、TestAuthorizationFilterAttrbuteクラスを次のように変更します.
public class TestAuthorizationFilterAttribute : AuthorizeAttibute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
Helper.Write("AuthorizationFilter", actionContext.RequestContext.Prioncipal);
//return base.IsAuthorized(actionContext);
return true;
}
}
3.15要求ルーティング:localhsot:8000/api/test表示------HttpModule------anonymous user------Middleware------anonymous user------AuthenticationFilter------anonymous user------AuthorizationFilter------anonymous user------anonymous user------anonymous userが表示され、ルーティングは安全なパイプラインを通るHttpModule,OWIN,AuthenticaitonFilter,AuthorizationFilter,Controller,まだユーザー情報が取得されていませんか?3.16ユーザー情報はどこから注入されますか?次にTestMiddlewareクラスを変更します
using Microsoft.Owin;
using System.Security.Principal;
namespace SecurityPopeline.Pipeline
{
public class TestMiddleware
{
private Func<IDictionary<string, object>, Task> _next;
public TestMiddleware(Func<IDictionary<string, object>, Task> next)
{
_next = next;
}
public async Task Invoke(IDictionary<string, object> env)
{
var context = new OwinContext(env);
//authentication
//new string[]
context.Request.User = new GenericPrincipal(new GenericIdentity("dom"),new string[]{});
Helper.Write("Middleware", context.Request.User);
await _next(env);
}
}
}
3.17要求ルーティング:localhsot:8000/api/test表示------HttpModule------anonymous user------Middleware------User:dom------AuthenticationFilter------User:dom------AuthorizationFilter------User:dom------Controller:domまとめ:通りかかったら、安全配管のHttpModule,OWIN,AuthenticaitonFilter,AuthorizationFilter,Controllerを通り、最後にActionに到着し、ユーザ情報はOWINに注入できる.