Objective
Whether it is an ASP. NET MVC or Web API framework, the authentication of request information from the request to the response, and the authorization of the access page after the success of the authentication are extremely important, with two sections to focus on both, this section first tells some basic information about both, In the next section, we will deepen our understanding of the two through actual combat and different ways of realization, and hope this article has gained some benefit to you.
Identity
Identity on behalf of authenticated users, let's take a look at the definition of this interface
public interface iidentity{ //Properties string AuthenticationType {get;} BOOL IsAuthenticated {get;} String Name {get;}}
The interface defines three read-only properties, AuthenticationType represents the type used for authentication, and isauthenticated represents the name of the identity if it has passed authentication. For AuthenticationType authentication identity types, different authentication identity types correspond to different identities, if Windows Integrated Authentication is used, the identity is WindowsIdentity, whereas for form forms authentication, The identity of the formsidentity, except for the two, we can also use the GenericIdentity object to represent the general meaning of the identity.
The properties in the Windowidentity object groups return the user group where the Windows account is located, and the attribute isguest is used to determine whether the account is in the Guest user group, and finally a IsSystem attribute that clearly indicates whether the account is a system account. In the case of anonymous logins, the object has a isanonymous to indicate whether the account is an anonymous account. And its method has a Getanonymous method to return an anonymous object's WindowsIdentity object, but this windowsidentity is just an empty object, unable to determine the corresponding Windows account.
Let's take a look at the definition of this object
public class formsidentity:claimsidentity {public formsidentity (FormsAuthenticationTicket ticket); Protected formsidentity (formsidentity identity); public override string AuthenticationType {get;} public override ienumerable<claim> Claims {get;} public override bool IsAuthenticated {get;} public override string Name {get;} Public FormsAuthenticationTicket Ticket {get;} public override Claimsidentity Clone (); }
A FormsIdentity object is created through an encrypted authentication ticket (authentication Ticket) or a security token, the encrypted content or a cookie or a requested URL. The following is the use of formsidentity to encrypt cookies.
var New FormsAuthenticationTicket (1"cookies", DateTime.Now, DateTime.Now.AddMinutes ( - true " UserData " , Formsauthentication.formscookiepath); var encriptdata = Formsauthentication.encrypt (ticket);
Both of these have their corresponding identity types, and if you want to customize the authentication method simply inherit the class, it represents a generic security identity. This class inherits from the IIdentity interface. As for how to determine an anonymous identity only through the user name, if the user name is empty, the property of the object isauthenticated to True, otherwise false.
PrincipalThis object contains two basic features, which are based on the user's security identity and the permissions that the user has, and authorization is the so-called permission is bound based on the role, so this object can be described as: "Identity" + "role".
First, let's take a look at this interface
public interface iprincipal{ bool IsInRole (string role); IIdentity Identity {get;}}
The above implementation based on the IIdentity interface is WindowsIdentity and GenericIdentity, and of course corresponds to the principal type namely WindowsPrincipal and GenericPrincipal, In addition to the RolePrincipal, the three are not in the narrative, we focus on the next Apicontroller in the IPrincipal attribute.
User in Apicontroller
Let's take a look at this user property
Public IPrincipal User {get;}
Go ahead and look at this property's get
Public IPrincipal user{ get { return thread.currentprincipal;} }
There's still nothing to see, even if you're looking at the VS compiler and you can't see what's going on, it's time to look at the official source code. As follows:
Public Httprequestcontext requestcontext { get { return controllercontext.requestcontext; } Set {...} } Public IPrincipal User { get {return requestcontext.principal;} set {Requestcontext.principal = value;} }
Here we see a little bit of a look.
the IPrincipal property of the user is obviously the current request and has the same reference as the property principal in Httprequestcontext.
so the question comes, where does httprequestcontext come from?
We know that there are two kinds of boarding mode, accesses than either is the web host, and the other accesses than either is the self Host, so the request context is different depending on the boarding mode, so let's take a look at the request context in Web host.
Internal class Webhosthttprequestcontext:httprequestcontext { private readonly httpcontextbase _contextbase ; Private ReadOnly httprequestbase _requestbase; Private ReadOnly httprequestmessage _request; public override IPrincipal Principal { get { return _contextbase.user; } Set { _contextbase.user = value; Thread.CurrentPrincipal = value;}} }
From here we can draw a conclusion:
The principal in Web host mode has the same reference as the user in the context of the current request, while the principal of the current thread is also modified when we modify the property principal.
Let's look at the implementation of principal in this homestay mode
Internal class Selfhosthttprequestcontext:httprequestcontext { private readonly RequestContext _ RequestContext; Private ReadOnly httprequestmessage _request; public override IPrincipal Principal { get { return thread.currentprincipal; } Set { Thread.CurrentPrincipal = value;}} }
In this mode we can draw the conclusion that:
The default for principal in the Self
host mode is to return the principal used by the current thread.
Let's take a look at certification (authentication) and authorization (Authorization).
Authenticationfilter
Authenticationfilter is the first filter filter to execute, because any send to server Request action method first has to authenticate its identity, and the authorization after the successful authentication is authorization of course after this filter, It is supported by MVC5 and Web API 2.0. Here is a picture to illustrate the position and relationship of the two in the pipeline.
Let's take a look at the first filter Authenticationfilter interface Iauthenticationfilter definition:
Public interface Iauthenticationfilter:ifilter { Task Authenticateasync (httpauthenticationcontext context, CancellationToken cancellationtoken); Task Challengeasync (httpauthenticationchallengecontext context, CancellationToken cancellationtoken); }
the interface defines two methods, one of which isAuthenticateasync, it primarily authenticates the user's credentials. The other is Challengeasync , which is primarily intended to send a challenge (Chanllenge) to the client in the event of authentication failure.
Both of the authentication methods are defined in the RFC2612 and RFC2617 of the HTTP protocol, and both are based on the following two points:
- If the client does not send any credentials to the server, it returns a 401 (unauthorized) response to the client, including a www-authenticate header in the response returned to the client, containing one or more challenges in the header, And each challenge will specify the authentication combination that is recognized by the server.
- After returning a 401 to the client from the server response, the client sends all the credentials in the authentication header.
Let's look at the contents of each method in detail:
Authenticateasync
The parameter type in this method is Httpauthenticationcontext, which is represented as the authentication context, and we look at the implementation of this class
public class Httpauthenticationcontext {public Httpauthenticati Oncontext (Httpactioncontext Actioncontext, IPrincipal principal) {if (Actioncontext = = null) {throw new ArgumentNullException ("Actioncontext"); } actioncontext = Actioncontext; Principal = Principal; Public Httpactioncontext Actioncontext {get; private set;} Public IPrincipal Principal {get; set;} Public Ihttpactionresult Errorresult {get; set;} Public Httprequestmessage Request {get {Contract.assert (Actioncontext! = nul L); return actioncontext.request; } } }
initialized with the principal property of the action context and authenticated user in the constructor, and the property Errorresult returns a Httpactionresult object that returns the error message directly to the client in the event of an authentication failure. We should be able to think of more than one Authenticationfilter request to the action method, when the Web API is sorted by Filterscope to form a Authenticationfilter pipeline, The authentication context is then created with the current action request context and the principal returned by the user property of Apicontroller. The final authentication context is invoked as an argument to the Authenticateasync method in the Authenticationfilter.
When execution is executed successfully for the Authenticateasync method and returns a specific httpactionresult, the subsequent operation terminates, and the next step is the "Send authentication challenge" phase of the second method.
ChallengeasyncMost of the certification is basically the "challenge-answer" approach, the server to the client to issue a challenge request to provide credentials, if the client after the implementation of the Authenticateasync method, the authentication is unsuccessful, At this point the server side will send the authentication challenge via the Challengeasync method.
Let's take a look at the concrete implementation of this approach
public class Httpauthenticationchallengecontext {private Ihttpactionresult _result; Public Httpauthenticationchallengecontext (Httpactioncontext actioncontext, ihttpactionresult result) {I F (Actioncontext = = null) {throw new ArgumentNullException ("Actioncontext"); } if (result = = null) {throw new ArgumentNullException ("result"); } actioncontext = Actioncontext; result = result; Public Httpactioncontext Actioncontext {get; private set;} Public Ihttpactionresult Result {get {return _result; } set {if (value = = null) {throw new argumentnull Exception ("value"); } _result = value; }} public httprequestmessage Request {gET {contract.assert (Actioncontext! = null); return actioncontext.request; } } }
obviously, when the Authenticateasync method is called to complete the authentication work, Errorresult will return a specific httpactionresult, The action context and the specific httpactionresult are passed to the constructor for initialization Httpauthenticationchallgecontext, and the Challengeasync method is called in turn, When this method is executed, the result property in this class returns a specific Httpactionresult object that creates the corresponding Httpresponsemessage object and responds to the message processing pipeline to issue the authentication challenge. Summarize
(1) Using Authenticationfilter for authentication in the Web API is mainly the following three steps
- The Web API creates all possible Authenticationfilter lists for each action method that needs to be called, and if more than one is ordered by Filterscope, the Authenticationfilter pipeline is eventually formed.
- The Web API calls the Authenticateasync method in turn for each filter in the Authenticationfilter pipeline, where each authenticationfilter validates the HTTP request credentials from the client. Even if an error is triggered during the authentication process, the process does not terminate at this time.
- If the authentication succeeds, the Web API will invoke the Challengeasync method for each authenticationfilter, and each authenticationfilter will then make a challenge response through this method.
(2) By the above description we use three sheets to see
Certification Scheme
We know that there are two authentication schemes in the HTTP protocol, one is basic Basic authentication, the other is Digest Digest authentication
Basic BASIC CertificationThis authentication is to send the user name and password in the form of colon and Base64 plaintext encoding in the client, but it is not very safe, because it is not encrypted, and it is a good authentication scheme to use HTTPS information channel encryption on this basis. Digest Digest CertificationThis certification is a basic basic certification of the upgrade version, the default is the use of MD5 encryption, to a certain extent is more secure, its execution process and basic basic certification, just like the algorithm generated is different. To be continued: The next step is to pass the certification scheme manually in different ways to achieve certification ...
WEB API Authentication (authentication) and authorization (Authorization) "One" (12)