Implementing a token Base authentication instance in ASP.

Source: Internet
Author: User
Previous authentication on the web is based on cookies | Session authentication, before there are no more terminals, there is no problem, but in the Web API era, you need to face more than just the browser, there are a variety of clients, so there is a problem, these clients do not know what the cookie is ghost. (Cookies are actually a small trick of the browser to keep the conversation, but the HTTP itself is stateless, and the various clients can provide nothing more than the HTTP API)

Token-based identity authentication is a response to this change, which is more open and secure.

Token-based authentication is implemented in many ways, but we only use the API provided by Microsoft.

The next example will lead you through a use of Microsoft Jwtsecuritytokenhandler to complete a Beare token-based identity authentication.

Note: This article is part of the step by step tutorial, so you don't have to look dizzy, it makes sense to download the full Code analysis code structure.

Create a project

Create a new project in VS, project type Select ASP. NET core Web application, and enter the project name as Cstokenbaseauth

Coding

Create some helper classes

Create a folder Auth under the project root and add RSAKeyHelper.cs and TokenAuthOption.cs two files

In the RSAKeyHelper.cs

Using System.Security.Cryptography; namespace cstokenbaseauth.auth{public  class Rsakeyhelper  {public    static RSAParameters GenerateKey ()    {      using (var key = new RSACryptoServiceProvider (2048))      {        return key. Exportparameters (True);}}}  

In the TokenAuthOption.cs

Using system;using Microsoft.IdentityModel.Tokens; namespace cstokenbaseauth.auth{public  class tokenauthoption  {public    static string audience {get;} = "E Xampleaudience ";    public static string Issuer {get;} = "Exampleissuer";    public static Rsasecuritykey Key {get;} = new Rsasecuritykey (Rsakeyhelper.generatekey ());    public static signingcredentials signingcredentials {get;} = new Signingcredentials (Key, Securityalgorithms.rsasha256signature);     public static TimeSpan Expiresspan {get;} = Timespan.fromminutes;}  }

Startup.cs

Add the following code to the Configureservices:

Services. Addauthorization (auth =>{  auth. Addpolicy ("Bearer", New Authorizationpolicybuilder ()    . Addauthenticationschemes (Jwtbearerdefaults.authenticationscheme)    . Requireauthenticateduser (). Build ());});

The complete code should be like this

public void Configureservices (iservicecollection services) {  //ADD framework services.  Services. Addapplicationinsightstelemetry (Configuration);  Enable the use of a [Authorize ("Bearer")] attribute on methods and classes to protect.  Services. Addauthorization (auth =  {    auth. Addpolicy ("Bearer", New Authorizationpolicybuilder ()      . Addauthenticationschemes (Jwtbearerdefaults.authenticationscheme)      . Requireauthenticateduser (). Build ());  });  Services. Addmvc ();}

Add the following code in the Configure method

App. Useexceptionhandler (AppBuilder = {Appbuilder.use) (Async (context, next) = {var = context.    Features[typeof (Iexceptionhandlerfeature)] as iexceptionhandlerfeature; When authorization have failed, should retrun a JSON message to client if (Error! = NULL && error. Error is securitytokenexpiredexception) {context.      Response.statuscode = 401; Context.      Response.ContentType = "Application/json"; Await the context.    Response.writeasync (Jsonconvert.serializeobject (New {authenticated = False, tokenexpired = true})); }//when orther error, retrun A error message JSON to client else if (Error! = NULL && error. Error! = null) {context.      Response.statuscode = 500; Context.      Response.ContentType = "Application/json"; Await the context. Response.writeasync (Jsonconvert.serializeobject (New {success = false, error = error.    Error.message}));    }//when no error, do next.  else await next (); });});

This code is mainly handle error, such as when the authentication fails to throw an exception, and this is the exception to handle this.

Next, add the following code to the same method,

App. Useexceptionhandler (AppBuilder = {Appbuilder.use) (Async (context, next) = {var = context.     Features[typeof (Iexceptionhandlerfeature)] as iexceptionhandlerfeature; When authorization have failed, should retrun a JSON message to client if (Error! = NULL && error. Error is securitytokenexpiredexception) {context.      Response.statuscode = 401; Context.       Response.ContentType = "Application/json"; Await the context.    Response.writeasync (Jsonconvert.serializeobject (New {authenticated = False, tokenexpired = true})); }//when orther error, retrun A error message JSON to client else if (Error! = NULL && error. Error! = null) {context.      Response.statuscode = 500; Context.      Response.ContentType = "Application/json"; Await the context. Response.writeasync (Jsonconvert.serializeobject (New {success = false, error = error.    Error.message}));    }//when no error, do next.  else await next (); });}); 

Application Jwtbearerauthentication

App. Usejwtbearerauthentication (new Jwtbeareroptions {  tokenvalidationparameters = new Tokenvalidationparameters {    Issuersigningkey = Tokenauthoption.key,    Validaudience = tokenauthoption.audience,    validissuer = Tokenauthoption.issuer,    Validateissuersigningkey = True,    Validatelifetime = True,    Clockskew = timespan.fromminutes (0)  });

The complete code should be like this

Using system;using microsoft.aspnetcore.builder;using microsoft.aspnetcore.hosting;using Microsoft.extensions.configuration;using microsoft.extensions.dependencyinjection;using Microsoft.extensions.logging;using microsoft.aspnetcore.authorization;using Microsoft.aspnetcore.authentication.jwtbearer;using cstokenbaseauth.auth;using Microsoft.AspNetCore.Diagnostics; Using microsoft.identitymodel.tokens;using microsoft.aspnetcore.http;using Newtonsoft.json;  Namespace cstokenbaseauth{public class startup {public Startup (Ihostingenvironment env) {var builder = new Configurationbuilder (). Setbasepath (env. Contentrootpath). Addjsonfile ("Appsettings.json", Optional:true, Reloadonchange:true). Addjsonfile ($ "appsettings.{ Env.       Environmentname}.json ", optional:true); if (env.  Isenvironment ("development")) {//This would push telemetry data through application Insights pipeline faster,        Allowing to view results immediately. Builder. AddAPplicationinsightssettings (developermode:true); } builder.      Addenvironmentvariables (); Configuration = Builder.    Build ();     } public iconfigurationroot Configuration {get;} This method gets called by the runtime. Use this method to add services to the container public void configureservices (iservicecollection services) {/      /ADD Framework Services. Services.       Addapplicationinsightstelemetry (Configuration);      Enable the use of a [Authorize ("Bearer")] attribute on methods and classes to protect. Services. Addauthorization (auth = {auth. Addpolicy ("Bearer", New Authorizationpolicybuilder (). Addauthenticationschemes (Jwtbearerdefaults.authenticationscheme). Requireauthenticateduser ().      Build ());       }); Services.    Addmvc (); }//This method gets called by the runtime. Use this method to configure the HTTP request pipeline public void Configure (Iapplicationbuilder app, Ihostingenvironme NT ENV, ILoggerfactory loggerfactory) {loggerfactory.addconsole (Configuration.getsection ("Logging"));       Loggerfactory.adddebug (); App.       Useapplicationinsightsrequesttelemetry (); App.       Useapplicationinsightsexceptiontelemetry (); #region Handle Exception App. Useexceptionhandler (AppBuilder = {Appbuilder.use) (Async (context, next) = {var = context.           Features[typeof (Iexceptionhandlerfeature)] as iexceptionhandlerfeature; When authorization have failed, should retrun a JSON message to client if (Error! = NULL && error. Error is securitytokenexpiredexception) {context.            Response.statuscode = 401; Context.             Response.ContentType = "Application/json"; Await the context.            Response.writeasync (Jsonconvert.serializeobject (New {authenticated = False, tokenexpired = true}          )); }//when orther error, retrun A error message json to client ElSE if (Error! = NULL && error. Error! = null) {context.            Response.statuscode = 500; Context.            Response.ContentType = "Application/json"; Await the context. Response.writeasync (Jsonconvert.serializeobject (New {success = false, error = error.          Error.message}));          }//when no error, do next.        else await next ();      });      }); #endregion #region usejwtbearerauthentication App.          Usejwtbearerauthentication (new Jwtbeareroptions {tokenvalidationparameters = new Tokenvalidationparameters { Issuersigningkey = Tokenauthoption.key, validaudience = tokenauthoption.audience, Validissuer = Toke Nauthoption.issuer, Validateissuersigningkey = True, Validatelifetime = true, Clockskew = times Pan.      Fromminutes (0)}); #endregion app. USEMVC (routes = {routes.        MapRoute (name: "Default",  Template: "{controller=login}/{action=index}");    }); }  }}

Create a new Web API Controller Class in controllers named TokenAuthController.cs. We will complete the login authorization here

Add two classes under the same file, respectively, to simulate the user model, and the user store, the code should be

public class user{Public  Guid ID {get; set;}  public string Username {get; set;}  public string Password {get; set;}} public static class userstorage{public  static list<user> Users {get; set;} = new List<user> {    new U Ser {id=guid.newguid (), username= "user1", Password = "USER1PSD"},    new User {id=guid.newguid (), username= "User2", Password = "USER2PSD"},    new User {id=guid.newguid (), username= "User3", Password = "USER3PSD"}  };

Next, add the following method in TokenAuthController.cs

private string Generatetoken (user user, DateTime expires) {  var handler = new Jwtsecuritytokenhandler ();     Claimsidentity identity = new Claimsidentity (    new GenericIdentity (user. Username, "Tokenauth"),    new[] {      new Claim ("ID", user.id. ToString ())    }  );   var SecurityToken = handler. Createtoken (New Securitytokendescriptor  {    Issuer = Tokenauthoption.issuer,    audience = Tokenauthoption.audience,    signingcredentials = tokenauthoption.signingcredentials,    Subject = identity,    Expires = Expires  });  Return handler. Writetoken (SecurityToken);}

This method simply generates a auth Token, and then we add another method to invoke it.

Add the following code to the same file

[Httppost]public string Getauthtoken (user user) {  var existuser = UserStorage.Users.FirstOrDefault (U + = u). Username = = user. Username && U.password = = user. Password);   if (existuser! = null)  {    var requestat = DateTime.Now;    var expiresin = Requestat + Tokenauthoption.expiresspan;    var token = Generatetoken (Existuser, expiresin);     Return Jsonconvert.serializeobject (New {      statecode = 1,      requertat = Requestat,      expiresin = TokenAuthOption.ExpiresSpan.TotalSeconds,      Accesstoken = token    });  }  else  {    return Jsonconvert.serializeobject (new {statecode =-1, errors = "Username or password is invalid"}); 
  }}

The complete code for the file should be like this

Using system;using system.collections.generic;using system.linq;using system.threading.tasks;using Microsoft.aspnetcore.mvc;using newtonsoft.json;using system.identitymodel.tokens.jwt;using System.Security.Claims ; using system.security.principal;using microsoft.identitymodel.tokens;using Cstokenbaseauth.auth; namespace cstokenbaseauth.controllers{[Route ("Api/[controller]")] public class Tokenauthcontroller:controller {[ HttpPost] public string getauthtoken (user user) {var existuser = UserStorage.Users.FirstOrDefault (U = u.us Ername = = user. Username && U.password = = user.       Password);        if (existuser! = null) {var requestat = DateTime.Now;        var expiresin = Requestat + Tokenauthoption.expiresspan;         var token = Generatetoken (Existuser, Expiresin); Return Jsonconvert.serializeobject (New {statecode = 1, Requertat = requestat, Expiresin = Toke NAuthOption.ExpiresSpan.TotalSeconds, Accesstoken = token}); } else {return Jsonconvert.serializeobject (new {statecode =-1, errors = "Username or password is inval      ID "}); }} private string Generatetoken (user user, DateTime expires) {var handler = new Jwtsecuritytokenhandler ()             ; Claimsidentity identity = new Claimsidentity (new GenericIdentity (user. Username, "Tokenauth"), new[] {new Claim ("ID", user.id.       ToString ())}); var SecurityToken = handler. Createtoken (new Securitytokendescriptor {Issuer = tokenauthoption.issuer, audience = Tokenauthoption.a Udience, signingcredentials = tokenauthoption.signingcredentials, Subject = identity, Expires = Expir      ES}); Return handler.    Writetoken (SecurityToken);     }} public class User {public Guid ID {get; set;}     public string Username {get; set;}  public string Password {get; set;}    } public static class Userstorage {public static list<user> Users {get; set;} = new List<user> {new User {id=guid.newguid (), username= ' use R1 ", Password =" USER1PSD "}, new User {Id=guid.newguid (), username=" User2 ", Password =" USER2PSD "}, new user {id=  Guid.NewGuid (), username= "User3", Password = "USER3PSD"}}; }}

Next we'll complete the Authorization verification Section

Create a new Web API Controller Class in controllers named ValuesController.cs

Add the following code to it

public string Get () {  var claimsidentity = user.identity as claimsidentity;   var id = claimsIdentity.Claims.FirstOrDefault (c = = C.type = = "id"). Value;   return $ "hello! {HttpContext.User.Identity.Name}, your ID is:{id} ";}

To add decorative properties to a method

[HttpGet] [Authorize ("Bearer")] The complete file code should be such using system.linq;using microsoft.aspnetcore.mvc;using Microsoft.aspnetcore.authorization;using System.Security.Claims; namespace cstokenbaseauth.controllers{  [Route ("Api/[controller]")] public  class Valuescontroller: Controller  {    [httpget]    [Authorize ("Bearer")] public    string Get ()    {      var claimsidentity = User.Identity as claimsidentity;       var id = claimsIdentity.Claims.FirstOrDefault (c = = C.type = = "id"). Value;       return $ "hello! {HttpContext.User.Identity.Name}, your ID is:{id} ";}}  }

Finally, let's add the view.

Create a new Web Controller Class in controllers named LoginController.cs

Where the code should be like this

Using MICROSOFT.ASPNETCORE.MVC; namespace cstokenbaseauth.controllers{  [Route ("[Controller]/[action]")] public  class Logincontroller: Controller  {public    iactionresult Index ()    {      return View ();  }}}

Create a new directory named login in the project views directory and create a new index.cshtml file in it.

The code should look like this.

The above is the whole content of this article, I hope that everyone's learning has helped, but also hope that we support PHP Chinese network.

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.