ASP. NET Web API Security pipeline, asp. netapi

Source: Internet
Author: User

ASP. NET Web API Security pipeline, asp. netapi

 

This article describes the Security pipelines of ASP. NET Web APIs. Here, the security pipeline refers to various components or processes experienced in the request and response process, such as IIS, HttpModule, OWIN, WebAPI, and so on. This pipeline is divided into two phases: one is the verification phase and the other is the authorization phase.

In ASP. NET Web API v1, the security pipeline is roughly like this:

→ Authentication: request to HttpModule in IIS
→ Authenticatin, the request comes to the HttpMessageHandler of the API
→ Authorization: Request comes to Authorization Filter
→ Authorization: request to Controller

When ASP. NET Web API comes to v2, the security pipeline is roughly:

→ Request to the OWIN component in the Host
→ The request comes to MessageHandler, global or according to each request
→ Request to Authentication Filter
→ Request to Authorization Filter

It can be seen that the OWIN component is added, and the OWIN component is open-source. On this basis, Microsoft has developed the Katana verification middleware.

We know that there are two ways to host ASP. NET Web APIs:

1. Web host, ASP. NET, IIS
2. Self-host, WCF,. NET Process

If you consider OWIN, it is:
1. IIS → ASP. NET + OWIN Bridge → OWIN → Web API + OWIN Adapter
2. Process/Host + OWIN Bridge → OWIN → Web API + OWIN Adapter

1. Understand the various components in the pipeline


1.1 OWIN Middleware

 

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) {// check the env set to verify env ["server. user "] = CreatePrincipal (); // set principal; await _ next (env );}}

 

The general working principle of OWIN middleware is: the Header, Body, route, and other information in the request is placed in the IDictionary <string, object> dictionary set, and the Invoke method is provided, place the obtained user information in env ["server. user "], and calls an action to process IDictionary <string, object> set.


1.2 Katana Authentication Middleware

This is a verification component developed by Microsoft Based on OWIN, which is roughly:

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        })    }}

As shown above, you can select the authentication method for the OWIN component.

1.3 Message Handler

Implemented globally or on a request. Roughly:

Public class MyHandler: DelegatingHandler {protected async override Task <HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken) {// check request var response = await base. sendAsync (request, cancellationToken); // check the response return response ;}}

 

Message Handler does not exist after ASP. net web api 2.

 

1.4 Authentication Filter

It can be configured globally:

WebApiConfig. cs
Config. Filters. Add (new HostAuthenticationFilter ("Bearer "));

Of course, the filter can also be placed on the controller and method layer:

[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){}}

If the authorization fails, error 401 is returned.

1.6 obtain the user's Identity

Obtain the User Identity through the User attribute of ApiController. Note that the User attribute value may be null.

2. Use examples to experience security Pipelines


2.1 custom HttpModule

First, the request must pass HttpModule. We need to customize an HttpModule to print the current user information through a moderator method.

 

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("\n");        }    }}

 

It can be seen that HttpContext. Current is of the IPrincipal type.

This is a Web project. You need to register the HTTP module.

 

<configuration>    <system.webServer>        <modules>            <add name="DemoModule" type="SecurityPipeline.HttpModule"/>        </modules>    </system.webServer></configuration>

 

If there is a default.html page under the example project, run the project and display default.html, the console prints the following information:

----- HttpModule -------
Anonymouse

Apparently, the custom Http Module works for the request, but currently the User information cannot be obtained from IPrincipal.

2.2 install ASP. NET Web API 2

2.3 create a controller

 

Using System. net. http; public class TestController: ApiController {public IHttpActionResult Get () {Helper. write ("Controller", User); // you can also get the User to Write // Helper. write ("Controller", Request. getRequestContext (). principal); return OK ();}}

 

Above, the IPincipal type is obtained through the User attribute of ApiController.

2.4 install Microsoft. Owin. Host. SystemWeb

2.5 install Microsoft. ASP. NET Web API 2.1 OWIN

2.6 create a Startup class

 

using OWin;using System.Web.Http;namespace SecurityPopeline{    public class Startup    {        public void Configuraiton()        {            var configuration = new HttpConfiguration();            configuration.Routes.MapHttpRoute("default", "api/{controller}");                    }    }}

Here, assign the HttpConfiguraton instance of the web api to the UseWebApi method of IAppBuilder of the owin class.

2.7 request route: localhsot: 8000/api/test

Display
------ HttpModule --------
Anonymous user

------ Controller --------
Anonymous user

It can be seen that the request passes through the HttpModule and Controller in the pipeline, but the user information is still not obtained.

2.8 create the TestMiddleware class

After entering the HttpModule, and before entering the Controller, this is the place where the OWIN component will survive.

 

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 add TestMiddleware to the Startup class

 

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 request route: localhsot: 8000/api/test

Display
------ HttpModule --------
Anonymous user

------ Middleware --------
Anonymous user

------ Controller ------
Anonymous user

It can be seen that the request passes through the HttoModule and OWIN in the pipeline all the way, and finally arrives at the Controller, but still does not get the user information.

3.11 add TestAuthenticationFilterAttribute class

There are also verified interfaces between OWIN and Controller, which is also an important part of the security pipeline.

 

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;            }        }    }}

 

Filter feature added to Controller

 

Using System. net. http; [TestAuthenticationFilter] public class TestController: ApiController {public IHttpActionResult Get () {Helper. write ("Controller", User); // you can also get the User to Write // Helper. write ("Controller", Request. getRequestContext (). principal); return OK ();}}

 

3.12 request route: localhsot: 8000/api/test

Display
------ HttpModule --------
Anonymous user

------ Middleware --------
Anonymous user

------ AuthenticationFilter --------
Anonymous user

------ Controller ------
Anonymous user

It can be seen that the user information is still not obtained for the HttpModule, OWIN, and authentication in the Request Path Security pipeline.

3.13 added the TestAuthorizationFilterAttrbute class

After verification and before entering the Controller or Action, an important member of the security pipeline is the authorization feature.

 

public class TestAuthorizationFilterAttribute : AuthorizeAttibute{    protected override bool IsAuthorized(HttpActionContext actionContext)    {        Helper.Write("AuthorizationFilter", actionContext.RequestContext.Prioncipal);                return base.IsAuthorized(actionContext);    }}

 

Added the authorization feature to the Controller.

 

Using System. net. http; [TestAuthenticationFilter] [TestAuthorizationFilter] public class TestController: ApiController {public IHttpActionResult Get () {Helper. write ("Controller", User); // you can also get the User to Write // Helper. write ("Controller", Request. getRequestContext (). principal); return OK ();}}

 

3.14 request route: localhsot: 8000/api/test

Display
------ HttpModule --------
Anonymous user

------ Middleware --------
Anonymous user

------ AuthenticationFilter --------
Anonymous user

------ AuthorizationFilter --------
Anonymous user

Error: Authorization has been denied for this request

It can be seen that an error is reported before the request reaches the Controller.

Therefore, modify the TestAuthorizationFilterAttrbute class as follows:

public class TestAuthorizationFilterAttribute : AuthorizeAttibute{    protected override bool IsAuthorized(HttpActionContext actionContext)    {        Helper.Write("AuthorizationFilter", actionContext.RequestContext.Prioncipal);                //return base.IsAuthorized(actionContext);        return true;    }}

 

3.15 request route: localhsot: 8000/api/test

Display
------ HttpModule --------
Anonymous user

------ Middleware --------
Anonymous user

------ AuthenticationFilter --------
Anonymous user

------ AuthorizationFilter --------
Anonymous user

------ Controller --------
Anonymous user

It can be seen that the route passes through the HttpModule, OWIN, AuthenticaitonFilter, AuthorizationFilter, and Controller in the security pipeline, and the user information is still not obtained?

3.16 where can I inject user information?

Next, modify the TestMiddleware class.

 

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 [] array stores the user context. request. user = new GenericPrincipal (new GenericIdentity ("dom"), new string [] {}); Helper. write ("Middleware", context. request. user); await _ next (env );}}}

 

3.17 request route: localhsot: 8000/api/test

Display
------ HttpModule --------
Anonymous user

------ Middleware --------
User: dom

------ AuthenticationFilter --------
User: dom

------ AuthorizationFilter --------
User: dom

------ Controller --------
User: dom


Summary: requests are sent all the way through the HttpModule, OWIN, AuthenticaitonFilter, AuthorizationFilter, and Controller in the security pipeline, and finally to the Action. User information can be injected into the OWIN.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.