.Net 3.x
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
JwtBearer 中间件,它重写了 HandleAuthenticateAsync 方法。
大致步骤如下:
读取 Http Request Header 中的 Authorization 信息
读取 Authorization 值里面的 Bearer 信息
验证 Bearer 是否合法,会得到一个 ClaimsPrincipal
使用 ClaimsPrincipal 构建一个 Ticket(票据)
调用 Options.Events.TokenValidated(context),用户可以重写此方法验证Token合法性
返回验证成功
Web API JWT 服务端
Step 1:安装所需的NuGet包
打开NuGet包管理器控制台,然后输入如下指令:
Install-Package Microsoft.AspNetCore.Authentication.JwtBearer
Install-Package System.IdentityModel.Tokens.Jwt
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"])) //对称密钥
};
});
generate token that is valid for 7 days
public interface IUserService
come from:
https://jasonwatmore.com/post/2019/10/11/aspnet-core-3-jwt-authentication-tutorial-with-example-api
{
"AppSettings": {
"Secret": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET, IT CAN BE ANY STRING"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
private string generateJwtToken(User user)
{
// generate token that is valid for 7 days
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
ASP.NET Core Custom Validate token JWT Middleware
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebApi.Services;
namespace WebApi.Helpers
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AppSettings _appSettings;
public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
{
_next = next;
_appSettings = appSettings.Value;
}
public async Task Invoke(HttpContext context, IUserService userService)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
if (token != null)
attachUserToContext(context, userService, token);
await _next(context);
}
private void attachUserToContext(HttpContext context, IUserService userService, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
// attach user to context on successful jwt validation
context.Items["User"] = userService.GetById(userId);
}
catch
{
// do nothing if jwt validation fails
// user is not attached to context so request won't have access to secure routes
}
}
}
}
ASP.NET Core Custom Authorize Attribute
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using WebApi.Entities;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = (User)context.HttpContext.Items["User"];
if (user == null)
{
// not logged in
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
}
}
}
Use the [Authorize] attribute on WebApi Controllers
using Microsoft.AspNetCore.Mvc;
using WebApi.Models;
using WebApi.Services;
namespace WebApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
private IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpPost("authenticate")]
public IActionResult Authenticate(AuthenticateRequest model)
{
var response = _userService.Authenticate(model);
if (response == null)
return BadRequest(new { message = "Username or password is incorrect" });
return Ok(response);
}
[Authorize]
[HttpGet]
public IActionResult GetAll()
{
var users = _userService.GetAll();
return Ok(users);
}
}
}
Step 4:配置同源策略CORS
配置同源策略CORS的目的,是设置允许符合条件的网站才能调用我们的web api接口。
mongodb async
public virtual async Task<List<Employee>> GetEmployeeByOpenId(string id)
{
var query = from ea in this._employeeRepository.Table
.Where(ea => ea.AuthorOpenid == id)
select ea;
var users = query.ToListAsync();
return await users;
}
客户端JWT
1.首先要进行登录,登录成功会有个token信息,将token保存起来。
2.向web api接口发送请求,每次请求的时候必须带上这个token。
故需要做2次请求(1,登录,拿到token 2,正式向接口请求数据)
https://www.tuicool.com/articles/V3qy2qV
Useful links
Role based JWT Tokens in ASP.NET Core APIs
JWT在ASP.NET Core3.1的实战博客
blog:https://www.cnblogs.com/yixuanhan/p/12593724.html
完整项目下载地址:https://gitee.com/hanyixuan_net/donet-core
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