受欢迎的博客标签

User DB - either Identity or custom store
Authorize your web api controller
Use JWT for generating JSON web token and validating them.
Provide access if only JWT validates. Excellent support in ASP.NET Core API
Provide Login (token generator API endpoint), pass JWT for further API calls as Authorization header

 

The flow seems to be:

A user visits your site
They see your client app (Angular/React etc.) login page
They submit their username/password
Your client app sends these credentials over to your ASP.NET Core web API (to an action whose sole job is to issue JWT tokens)
The web API checks the credentials against a user store (often a database)
If the credentials are valid
Your web API issues a JWT token back to the client app

 

在asp .net core 程序中,实现认证有以下几种方式,开发时,需选择其中的一种。这次,我们选择JWT认证方式。

Microsoft.AspNetCore.Authentication
Microsoft.AspNetCore.Authentication.Cookies
Microsoft.AspNetCore.Authentication.OAuth
Microsoft.AspNetCore.Authentication.OpenIdConnect
Microsoft.AspNetCore.Authentication.JwtBearer

 

Web API JWT 服务端

Step 1:安装所需的NuGet包

打开NuGet包管理器控制台,然后输入如下指令:

Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
Install-Package Microsoft.IdentityModel.Tokens

 

step 2:在项目根目录“Startup”类,配置JWT验证方式

首先,要将网站的认证方式配置为JWT验证方式。

配置WebAPI之前我先安装一些NuGet包。

安装Nuget包:

using Microsoft.IdentityModel.Tokens;

Microsoft.AspNetCore.Authentication.JwtBearer

 

ConfigureServices method中,添加JWT验证方式代码

 services.AddAuthentication((opts =>
            {
                opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;  //如果不加这行,将会跳转到/Account/Login,也就是说你可以用视图来处理未登录
            })) //设置验证方式为常量Bearer,即JWTBearer
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true, //验证发行方
                        ValidateAudience = true, //验证听众api
                        ValidateLifetime = true, //验证生存时间
                        ValidateIssuerSigningKey = true, //验证发行方密钥
                        ValidIssuer = Configuration["JwtIssuer"], //发行方
                        ValidAudience = Configuration["JwtAudience"], //听众
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"])) //对称密钥
                    };
                });

 

Step 4:配置同源策略CORS

配置同源策略CORS的目的,是设置允许符合条件的网站才能调用我们的web api接口。

 

 

 

客户端JWT

1.首先要进行登录,登录成功会有个token信息,将token保存起来。

2.向web api接口发送请求,每次请求的时候必须带上这个token。

故需要做2次请求(1,登录,拿到token 2,正式向接口请求数据)

 

https://www.tuicool.com/articles/V3qy2qV

In this blog post I’ll explain how you can use Json Web Tokens (JWT) to secure a Web Api in ASP.NET Core. There’s a demo project in github that you can use to follow along. Using a token instead of a cookie On a web application where you don’t plan to have an API that is being consumed by for example a mobile app, typically a cookie is used to represent a signed-in user. The normal flow is: the user clicks login, goes to a login page and after entering valid credentials the response that is sent to the user’s browser contains a Set-Cookie header that contains encrypted information. Every time a cookie is set for a domain, e.g. blinkingcaret.com, on every request the browser sends to that domain the cookie will be automatically included. On the server that cookie is decrypted and its contents are used to create the user’s identity. This process works very well if the client is a browser, it’s a different story when we the client is a mobile app. JWT What we can use instead of a cookie is a token. A token also represents the user, but when we use it we don’t rely on the browser’s built-in mechanism to deal with cookies. We have to explicitly ask for a token, store it ourselves somewhere, and then manually send it with every request. There are some ways to make this as painless as possible and I’ll discuss some of them later in this the post. The token format I’ll be talking about here is JWT. JWT stands for Json Web Token. A JWT token has the following format base64-encoded-header.base64-encoded-payload.signature. An example of a header is{“alg”: “HS265”,“typ”: “JWT”} The payload contains a list of claims, for example: { "name": "Rui", "admin": true } Finally the signature is created by taking: “base64(header).base64(payload)” and cryptographically signing it using the algorithm specified in the header. For example HMAC-SHA256. The signing part involves using a secret that is only known at the server. Here’s how a real JWT looks like: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoicnVpIiwic3ViIjoidGVzdCIsIm5iZiI6MTUwMzYxNDU4NSwiZXhwIjoxNTA2MDMzNzg1LCJpc3MiOiJibGlua2luZ2NhcmV0IHN0cyIsImF1ZCI6ImJsaW5raW5nY2FyZXQgYXBwIn0.F7PFoYcQXez3zV98BFKLpyON6d_1p-6IAeihZRSv0VM It is important to be aware that the information contained in the JWT is not encrypted. To get the payload you just need to base64-decode it. You can even do that from your developer tools console (for example in chrome). Use the atob method and pass the payload as an argument. You’ll see that you’ll get JSON back. The signature guarantees that if someone tries to replace the payload, the token becomes invalid. For someone to be successful in replacing the payload and producing a valid token they would need to know the secret used in the signature, and that secret never goes to the client. This is something to have in mind when you decide what to put in the payload. Using JWT in ASP.NET Core To use JWT in ASP.NET Core we need to know how to manually create JWT tokens, how to validate them and how to create an endpoint so that the client app can request them. How to create a JWT token First you need to install the package System.IdentityModel.Tokens.Jwt: $ dotnet add package System.IdentityModel.Tokens.Jwt Now we need to create a secret key. We are going to use a symmetric key, here’s how we can do that: var secretKey = new SymmetricSecurityKey(Endoding.UTF8.GetBytes("a secret that needs to be at least 16 characters long")); Our token will contain a set of claims. So lets create them: var claims = new Claim[] { new Claim(ClaimTypes.Name, "John"), new Claims(JwtRegisteredClaimNames.Email, "john.doe@blinkingcaret.com") } I’ve used both ClaimTypes (from System.Security.Claims) and JwtRegisteredClaimNames (from System.IdentityModel.Tokens.Jwt) to highlight that JwtRegisteredClaimNames contains the claims that are enumerated in the JWT RFC. You should use those as much as possible if you are planning to use the produced tokens with different frameworks for compatibility reasons. However, there are some claim types that enable certain functionalities in ASP.NET. For example ClaimTypes.Name is the default claim type for the user’s name (User.Identity.Name). Another example is ClaimTypes.Role that will be checked if you use the Roles property in an Authorize attribute (e.g. [Authorize(Roles="Administrator")]). After creating the list of claims we want to encode in the token we can create the token itself, here’s how we can do it: var token = new JwtSecurityToken( issuer: "your app", audience: "the client of your app", claims: claims, notBefore: DateTime.Now, expires: DateTime.Now.AddDays(28), signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256) ); There are a few concepts here that I didn’t mention before, namely the issuer, audience and expiration dates. The issuer represents the entity that generates the tokens, in this case it will be the ASP.NET Core web application. The audience is who the tokens are intended to, i.e. the client application. This issuer and the audience are important if your are relying on a third party to create the tokens (not the case here). You can validate both the issuer and the audience when you validate the token. The notBefore and expires define after what point in time the token can be used and until when it is valid, respectively. Finally in the signingCredentials you specify which security key and what algorithm to use to create the signature. In the example we used HMAC-SHA256. If you don’t care about the issuer and audience (which are optional in the JWT specification), you can use the simpler constructor overload of JwtSecurityToken that expects a JwtSecurityHeader and JwtSecurityPayload. You’ll have to manually add the expires and notBefore claims yourself to the payload, for example: var claims = new Claim[] { new Claim(ClaimTypes.Name, "John"), new Claims(JwtRegisteredClaimNames.Email, "john.doe@blinkingcaret.com"), new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds()}"), new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") } var token = new JwtSecurityToken(new JwtHeader(new SigningCredentials(key, SecurityAlgorithms.HmacSha256)), new JwtPayload(claims)); Note that the Exp (expires) and Nbf (notBefore) claims’ value is a string with Unix time. The easiest way to convert a DateTime to that format is using DateTimeOffset. After creating an instance of JwtSecurityToken, the way to actually generate the token is to call the WriteToken method of an instance of JwtSecurityTokenHandler and pass the JwtSecurityToken as a parameter: string jwtToken = new JwtSecurityTokenHandler().WriteToken(token); Creating an endpoint to get the token Now that we know how to create our JWT tokens we need a way to enable the client to get them. The easiest way to do that is to create a web api controller action that expects a post request, for example, this would work: public class TokenController : Controller { [Route("/token")] [HttpPost] public IActionResult Create(string username, string password) { if (IsValidUserAndPasswordCombination(username, password)) return new ObjectResult(GenerateToken(username)); return BadRequest(); } //... Where in IsValidUserAndPasswordCombination you can use, for example ASP.NET Identity to validate the user’s credentials (if you need a resource for how to setup ASP.NET Identity check ASP.NET Identity Core From Scratch). GenerateToken is the process we just described in the previous section. Validating the token and “signing in” the user Now that we have a way to issue tokens we need a way to validate them. We’ll be using ASP.NET Core’s authentication middleware and configure it to accept JWT tokens. Add the Microsoft.AspNetCore.Authentication.JwtBearer NuGet package to your project. $ dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer Next open Startup.cs and update the ConfigureServices method: public void ConfigureServices(IServiceCollection services) { //... services.AddAuthentication(options => { options.DefaultAuthenticateScheme = "JwtBearer"; options.DefaultChallengeScheme = "JwtBearer"; }) .AddJwtBearer("JwtBearer", jwtBearerOptions => { jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your secret goes here")), ValidateIssuer = true, ValidIssuer = "The name of the issuer", ValidateAudience = true, ValidAudience = "The name of the audience", ValidateLifetime = true, //validate the expiration and not before values in the token ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date }; }); } If you are not familiar with ASP.NET Core’s authentication middleware I recommend reading External Login Providers in ASP.NET Core. Even though it’s about enabling signing in through Google, Facebook, etc it provides a detailed explanation of how authentication middleware works. Also, be aware that this is the new ASP.NET Core 2.0 syntax where authentication is fully configured via the ConfigureServices method, however the concepts are the same. More importantly in this example is the TokenValidationParameters class. It’s the class you have to instantiate to configure how the token should be validated. In Startup.cs you need to update the Configure method and add the authentication middleware: public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //... app.UseAuthentication(); //needs to be up in the pipeline, before MVC //... app.UseMvc(ConfigureRoutes); //.. Client The web api client can be a desktop app, mobile or even a browser. The example I’ll be describing is that of a web application that signs in, saves the token and then uses it to perform authenticated requests. You can find a working example here. First, to sign in you need to send a POST request to “/token” (or wherever you’ve setup the web api endpoint to generate the token) with a username and password. You can easily do that with jQuery: $.post("/token", $.param({username: "the username", password: "the password"})).done(function(token){ //save the token in local storage localStorage.setItem("token", token); //... }).fail(handleError); If all goes well with the POST you get the JWT back and you can save it somewhere, usually in local storage in the case of a web application. On mobile it depends on the platform you are using but they all have facilities that allow you to save the token (e.g. Android’s SharedPreferences). For the authentication middleware in the previous section to accept a JWT token and transform it in a User that you can then access in your controller action the request must have an Authorization header. The value of the header should be “Bearer ” followed by the JWT token, for example: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1l... Although you can “manually” add the Authorization header to every request, there’s usually ways to do that automatically. For example in jQuery there’s an event that you can use that runs before every request where you can check if you have a saved token, and if that’s the case, add the Authorization header to the request: $.ajaxSetup({ beforeSend: function(xhr) { if (localStorage.getItem("token") !== null) { xhr.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem("token")); } } }); There are similar mechanisms if you are using other frameworks, for example Angular has HttpInterceptors. Finally, to logout you just need to remove the token from local storage: localStorage.removeItem("token") One thing to be aware of is that if the client performs an action that requires the user to be authenticated and there’s no (valid) Authorization header in the request, the server will respond to that request with a response with status code 401. The response will also have a WWW-Authenticate:Bearer header. If you receive a response like this you can notify the user that authentication is required..

 

ASP.NET Core 3.0 - JWT Authentication Tutorial with Example API

ASP.NET Core 3.1 - JWT Authentication Tutorial with Example API

Authentication with client-side Blazor using JWT WebAPI and ASP.NET Core Identity

翻译链接:https://www.cnblogs.com/chen8854/p/11792986.html