.net 默认新建Api项目不需要额外从Nuget添加Microsoft.AspNetCore.Authentication.JwtBearer
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"Authentication": {
//私钥必须16位
"SecretKey": "YpdCP1VHoWkNawmb",
//谁签发的(发布者)
"issuer": "issuer",
//签发给谁(持有者)
"audience": "audience"
}
}
AuthController,具体登录实现可参考我以前文章Identity用户管理入门五(登录、注销)
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;namespace Shop.WebHost.Controllers
{
[Route("auth")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IConfiguration _configuration; public AuthController(IConfiguration configuration)
{
_configuration = configuration;
}
// GET: api/<AuthController>
[AllowAnonymous]
[HttpPost("Login")]
public ActionResult Login([FromForm] UserDto loginUser)
{
//模拟登陆用户提交数据
//以下假设登陆验证通过 // JWT主要由三部分组成:HEADER.PAYLOAD.SIGNATURE // HEADER,加密算法和签名的类型,加密算法是HmacSha256
const string signingAlgorithm = SecurityAlgorithms.HmacSha256; //Payload,如用户名,角色等信息,过期日期等,因为是未加密的,所以不建议存放敏感信息。
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, "user_id"), //红色字体为登录后获取的实际用户ID
//用户角色
new Claim(ClaimTypes.Role,"Admin"), //红色字体为用户登录后获取的实际用户角色
};
//Signiture从配置文件获取私钥
var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
//使用非对称算法对私钥进行加密
var signingKey = new SymmetricSecurityKey(secretByte);
//使用HmacSha256验证非对称加密后的私钥
var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm); //创建Jwt Token
var token = new JwtSecurityToken(
//谁发布的token
issuer: _configuration["Authentication:issuer"],
//发布给谁
audience: _configuration["Authentication:audience"],
//Payload
claims,
//发布时间
notBefore: DateTime.UtcNow,
//有效期s
expires: DateTime.UtcNow.AddDays(1),
//数字签名
signingCredentials
);
return Ok(new JwtSecurityTokenHandler().WriteToken(token));
}
} public class UserDto
{
public string UserName { get; set; }
public string Password { get; set; }
}
}
Startup.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Text;namespace Shop.WebHost
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
//Jwt认证服务
//AddAuthentication注册认证服务
//JwtBearerDefaults.AuthenticationScheme身份认证类型
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
//Jwt身份认证
.AddJwtBearer(option =>
{
//从配置文件读取私钥
var secretByte= Encoding.UTF8.GetBytes(Configuration["Authentication:SecretKey"]);
//身份认证参数
option.TokenValidationParameters = new TokenValidationParameters()
{
//验证发布者
ValidateIssuer = true,
ValidIssuer = Configuration["Authentication:issuer"], //验证持有者
ValidateAudience = true,
ValidAudience = Configuration["Authentication:audience"], //验证是否过期
ValidateLifetime = true, //加密私钥
IssuerSigningKey = new SymmetricSecurityKey(secretByte)
};
});
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Shop.WebHost", Version = "v1" });
});
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Shop.WebHost v1"));
} app.UseHttpsRedirection(); //你在哪
app.UseRouting();
//你是谁
app.UseAuthentication();
//你可以干什么
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
在控制器方法中增加【Authorize】即可未登录用户不能访问
控制用户组访问[Authorize(Roles = “Admin”)]
// 由于我们没有将身份验证中间件配置为自动运行并创建身份,
// 因此在授权时必须选择要使用的中间件。
// 选择要授权的中间件的最简单方法是使用ActiveAuthenticationSchemes属性
[Authorize(AuthenticationSchemes = “Bearer”)]
访问方式在header中增加(具体格式是Authorization:Bearer+空格+具体Token)
Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyX2lkIiwibmJmIjoxNjA3MzI1NzkxLCJleHAiOjE2MDc0MTIxOTEsImlzcyI6Imlzc3VlciIsImF1ZCI6ImF1ZGllbmNlIn0.ZEN3m7XP8u-u9CNkVf1tfeznqh1SuK7Y0wD1bq9rSfQ
获取当前登录用户ID
startup.cs增加HttpContextAccessor服务并注入HttpContext的访问器对象IHttpContextAccessor来获取当前的HttpContext
services.AddHttpContextAccessor();
private readonly IHttpContextAccessor _httpContextAccessor;public AuthController(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
增加获取当前用户ID方法
[HttpGet(nameof(GetCurrUserIdAsync))]
public async Task<string> GetCurrUserIdAsync()
{
var auth = await _httpContextAccessor.HttpContext!.AuthenticateAsync();//获取登录用户的AuthenticateResult
if (!auth.Succeeded) return null;
var userCli = auth.Principal?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier); //在声明集合中获取ClaimTypes.NameIdentifier 的值就是用户ID
if (userCli == null || string.IsNullOrEmpty(userCli.Value))
{
return null;
}
return userCli.Value;
}
或者使用
return _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
查询出当前用户ID就可以根据Identity用户管理入门二(显示用户列表)显示用户详情