ASP. NET Core 2.0 Web API based on JWT custom policy authorization

Source: Internet
Author: User

JWT (JSON Web token) is a JSON-based authentication mechanism with the following process:

By logging in to get tokens, and then appending the credentials of authorization to token in the header of each request, the server-side verification may obtain the resources that you want to access. About JWT technology, you can refer to the article on the network, here do not elaborate,

This blog post focuses on the set of permissions for the JWT-based Web API in ASP. NET Core 2.0, that is, how JWT is used in ASP. Again, different users or roles will not be able to access resources that they should not access because of permissions issues.

The basic idea is that we customize a policy to validate the user, and to authenticate the user authorization, permissionrequirement is the parameter that verifies the transfer authorization. Configureservices Injection Verification (authentication), Authorization (Authorization), and JWT (Jwtbearer) in startup

Custom policies:

has been closed to the AUTHORIZEROLICY.JWT NuGet package and posted to NuGet:

https://www.nuget.org/packages/AuthorizePolicy.JWT/

The source code is as follows:

JwtToken.cs

        <summary>///Get a JWT-based token///</summary>//<param name= "username" >& lt;/param>//<returns></returns> public static dynamic Buildjwttoken (claim[] claims, permis            Sionrequirement permissionrequirement) {var now = Datetime.utcnow; var JWT = new Jwtsecuritytoken (Issuer:permissionRequirement.Issuer, audience:permissionre Quirement. Audience, Claims:claims, Notbefore:now, Expires:now.            ADD (permissionrequirement.expiration), signingCredentials:permissionRequirement.SigningCredentials            ); var encodedjwt = new Jwtsecuritytokenhandler ().            Writetoken (JWT); var response = new {Status = true, Access_token = ENCODEDJWT, exp ires_in = permissionRequirement.Expiration.TotalMilliseconds, Token_type ="Bearer"};        return response; }

  

Permission.cs

    <summary>    ///user or role or other credential entity///    </summary> public    class Permission {//        < Summary>        ///user or role or other credential name///        </summary> public        virtual string name        {get; set;}        <summary>///Request URL///        </summary> public        virtual string URL        {get; set;}    }

PermissionRequirement.cs

    <summary>///Required parameters///</summary> public class Permissionrequirement:iauthorizationrequire ment {//<summary>///user rights set///</summary> public list<permission> Pe        rmissions {get; private set;}        <summary>///No Permissions action///</summary> public string Deniedaction {get; set;}         <summary>////Authentication Authorization type///</summary> public string ClaimType {internal get; set;} <summary>///request Path///</summary> public string Loginpath {get; set;} = "/A        Pi/login ";        <summary>///issuer///</summary> public string Issuer {get; set;}        <summary>///subscriber///</summary> public string Audience {get; set;} <summary>///expiry time///</summary> public TimeSpan expiration {get; set;        } = Timespan.fromminutes (5000);  <summary>///Signature Verification///</summary> public signingcredentials signingcredentials {get; Set }//<summary>//construction//</summary>//<param name= "Deniedaction" > No Permissions acti  on</param>//<param name= "userpermissions" > User Rights Collection </param>//<summary>// Construction//</summary>//<param name= "deniedaction" > Reject request url</param>//<param NA Me= "Permissions" > Permission set </param>//<param name= "ClaimType" > Claim type </param>//<param NA Me= "Issuer" > Issuer </param>//<param name= "Audience" > Subscribers </param>//<param name= "sign Ingcredentials "> Signature validation Entity </param> public permissionrequirement (String deniedaction, list<permission> PE Rmissions, String claimtype, string issuer, string audience, Signingcredentials signingcredentials)        {claimtype = ClaimType;            Deniedaction = deniedaction;            Permissions = Permissions;            Issuer = Issuer;            audience = audience;        Signingcredentials = signingcredentials; }    }

Custom policy class permissionhandler.cs

    <summary>//Authority handler///</summary> public class Permissionhandler:authorizationhandle        r<permissionrequirement> {//<summary>/////for validation programs///</summary>        Public iauthenticationschemeprovider schemes {get; set;}        <summary>////Custom policy parameters////</summary> public permissionrequirement requirement        {get; set;}        <summary>//construction///</summary>//<param name= "schemes" ></param>        Public Permissionhandler (Iauthenticationschemeprovider schemes) {schemes = schemes; } protected override Async Task Handlerequirementasync (authorizationhandlercontext context, permissionrequiremen            T requirement) {////Assignment user rights requirement = requirement; Convert from Authorizationhandlercontext to HttpContext to take out table for information var HttpContext = (Context. Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).            HttpContext;              Request URL var questurl = HttpContext.Request.Path.Value.ToLower (); Determines whether the request stops var handlers = httpcontext.requestservices.getrequiredservice<iauthenticationhandlerprovider> (            ); foreach (var scheme in await Schemes.getrequesthandlerschemesasync ()) {var Handler = await hand Lers. Gethandlerasync (HttpContext, Scheme.                Name) as Iauthenticationrequesthandler; if (handler! = null && await handler. Handlerequestasync ()) {context.                    Fail ();                Return }}//To determine if the request has credentials, that is, there is no login var defaultauthenticate = await Schemes.getdefaultauthenticatesch            Emeasync (); if (defaultauthenticate! = null) {var result = await Httpcontext.authenticateasync (defaultauthe Nticate.                Name); //result?. Principal is not empty, the login succeeds if (result?). Principal = null) {HttpContext.User = result.                    Principal; Whether the requested URL exists in the permission if (Requirement.Permissions.GroupBy (g = g.url). Where (w = w.key.tolower () = = Questurl). Count () > 0) {var name = HttpContext.User.Claims.SingleOrDefault (s = = S.T ype = = requirement. ClaimType).                        Value; Verify Permissions if (Requirement.Permissions.Where (w = w.name = = Name && w.url.tolower () = = Quest URL). Count () <= 0) {//no permission to jump to denied page HTTPCONTEXT.R Esponse. Redirect (requirement.                        Deniedaction); }} context.                    SUCCEED (requirement);                Return }}//To determine if there is no login, whether to access the URL of the login, and is a POST request, and Help is the form form submission type, otherwise the failure if (!qUesturl.equals (Requirement.LoginPath.ToLower (), stringcomparison.ordinal) && (! HttpContext.Request.Method.Equals ("POST") | | !httpcontext.request.hasformcontenttype)) {context.                Fail ();            Return } context.             SUCCEED (requirement); }    }

  

Create a new ASP. NET Core 2.0 Web API project and add AUTHORIZEPOLICY.JWT to the project

First set up the profile, the user can define the key and the person, subscribers

"Audience": {

"Secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",

"Issuer": "GSW",

"Audience": "Everone"

}

Injection validation (authentication), Authorization (Authorization), and JWT (Jwtbearer) in configureservices

Startup.cs

        public void Configureservices (iservicecollection services) {//Read config file var audiencecon            Fig = configuration.getsection ("Audience");            var symmetricKeyAsBase64 = audienceconfig["Secret"];            var Keybytearray = Encoding.ASCII.GetBytes (symmetricKeyAsBase64);            var signingkey = new Symmetricsecuritykey (Keybytearray);                 var tokenvalidationparameters = new Tokenvalidationparameters {Validateissuersigningkey = True, Issuersigningkey = Signingkey, Validateissuer = true, Validissuer = Audience                config["Issuer"], Validateaudience = true, Validaudience = audienceconfig["Audience"],            Validatelifetime = true, Clockskew = TimeSpan.Zero};            var signingcredentials = new Signingcredentials (Signingkey, securityalgorithms.hmacsha256); Services.     Addauthorization (options =       {//This collection simulates the user permission table, which can be queried from the database var permission = new List<permission> { New Permission {url= "/", name= "admin"}, new Permission {url= "/api/values  ", name=" admin "}, new Permission {url="/", Name=" System "}, New                Permission {url= "/api/values1", Name= "System"}}; If the third argument is Claimtypes.role, the name of each element of the above collection is the role name, if Claimtypes.name, that is, the name of each element of the above collection is the user name Var Permissionrequirem ent = new Permissionrequirement ("/api/denied", permission, Claimtypes.role, audienceconfig["Issuer"], audienceconfig[                "Audience"], signingcredentials); Options. Addpolicy ("Permission", policy = policy.            Requirements.add (permissionrequirement)); }). Addauthentication (options = options. Defaultauthenticatescheme = Jwtbearerdefaults.authenTicationscheme; Options.            Defaultchallengescheme = Jwtbearerdefaults.authenticationscheme; })            .                Addjwtbearer (o = = {//do not use HTTPS O.requirehttpsmetadata = false;            O.tokenvalidationparameters = tokenvalidationparameters;            }); Inject authorized handler services.            Addsingleton<iauthorizationhandler, permissionhandler> (); Services.        Addmvc (); }

  

Adding authorization features on a controller that needs to be granted

[Authorize ("Permission")]

The Permissioncontroller class has two methods, one is login, verify the user name and password is correct, if the correct token, if the failure, verification fails, not a successful login after the permission to navigate the action.

    [Authorize ("Permission")] public class Permissioncontroller:controller {//<summary>//        Custom policy parameters///</summary> permissionrequirement _requirement; Public Permissioncontroller (Iauthorizationhandler authorizationhander) {_requirement = (Authorizationha NDEr as Permissionhandler).        requirement; } [allowanonymous] [HttpPost ("/api/login")] public iactionresult Login (string username,string passwor            d,string role) {var isvalidated = Username = = "GSW" && password = = "111111"; if (!isvalidated) {return new Jsonresult (new {Status = False            , Message = "Authentication Failed"}); } else {//If it is a role-based authorization policy, add the user here, and if it is a role-based authorization policy, add the role Var claims =new claim[]{New Claim (Claimtypes.name, username), new Claim (Claimtypes.role, role)};                 User ID var identity = new Claimsidentity (jwtbearerdefaults.authenticationscheme); Identity.                Addclaims (claims);                Login Httpcontext.signinasync (Jwtbearerdefaults.authenticationscheme, New ClaimsPrincipal (identity));                var token = Jwttoken.buildjwttoken (claims, _requirement);            return new Jsonresult (token);            }} [AllowAnonymous] [HttpGet ("/api/denied")] public Iactionresult denied () {        return new Jsonresult (new {Status = false, Message = "You have no Access"}); }    }

  

The following defines a console (. Netframewrok) program, with Restsharp to access our defined Web API, where 1 is the admin role login, 2 for the system role login, 3 for the wrong user password login, 4 is a query function, In Startup.cs, the admin role has the right to query/api/values, so with admin login is able to access the normal, with the system login, can successfully login, but no access to/api/values, user name password error, Access/aip/ Values, Direct is not authorized

  Class Program {///<summary>///visit URL//</summary> static string _url = "        http://localhost:39286 ";            static void Main (string[] args) {dynamic token = null;                while (true) {Console.WriteLine ("1, Login" admin "2, Login" System "3, Login" error username password "4, query Data");                var mark = Console.ReadLine ();                var stopwatch = new Stopwatch (); Stopwatch.                Start ();                        Switch (Mark) {case "1": token = Adminlogin ();                    Break                        Case "2": token = Systemlogin ();                    Break                        Case "3": token = Nulllogin ();                    Break                        Case "4": Admininvock (token);                Break } stopwatch.              Stop ();  TimeSpan timespan = stopwatch.                Elapsed; Console.WriteLine ($ "interval time: {TimeSpan.            TotalSeconds} ");            }} static dynamic Nulllogin () {var loginclient = new Restclient (_url);            var loginrequest = new Restrequest ("/api/login", method.post);            Loginrequest.addparameter ("username", "Gswaa");            Loginrequest.addparameter ("Password", "111111");            or the user name password to query the corresponding role Loginrequest.addparameter ("Role", "system");            Irestresponse loginresponse = Loginclient.execute (loginrequest);            var logincontent = loginresponse.content;            Console.WriteLine (logincontent);        Return Newtonsoft.Json.JsonConvert.DeserializeObject (logincontent);            } static dynamic Systemlogin () {var loginclient = new Restclient (_url);            var loginrequest = new Restrequest ("/api/login", method.post);            Loginrequest.addparameter ("username", "GSW"); LOginrequest.addparameter ("Password", "111111");            or the user name password to query the corresponding role Loginrequest.addparameter ("Role", "system");            Irestresponse loginresponse = Loginclient.execute (loginrequest);            var logincontent = loginresponse.content;            Console.WriteLine (logincontent);        Return Newtonsoft.Json.JsonConvert.DeserializeObject (logincontent);            } static dynamic Adminlogin () {var loginclient = new Restclient (_url);            var loginrequest = new Restrequest ("/api/login", method.post);            Loginrequest.addparameter ("username", "GSW");            Loginrequest.addparameter ("Password", "111111");            or the user name password to query the corresponding role Loginrequest.addparameter ("role", "admin");            Irestresponse loginresponse = Loginclient.execute (loginrequest);            var logincontent = loginresponse.content;            Console.WriteLine (logincontent); Return Newtonsoft.Json.JsonConvert.DeserializeObject (logIncontent);            } static void Admininvock (Dynamic token) {var client = new Restclient (_url); This is to add Bearer string tk = "Bearer" + convert.tostring (token?) before getting a token string.            Access_token); Client.            Adddefaultheader ("Authorization", TK);            var request = new Restrequest ("/api/values", method.get); Irestresponse response = client.            Execute (Request); var content = Response.            Content; Console.WriteLine ($ "Status: {Response.        StatusCode} return Result: {content} "); }    }

  

Operation Result:

Source:Https://github.com/axzxs2001/AuthorizePolicy.JWT

ASP. NET Core 2.0 Web API based on JWT custom policy authorization

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.