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.