1. 创建好项目,添加一个控制器,新建用户登录api接口和接收用户登录信息类Dto
Dto就包含两个字段,账号和密码
2. 安装NuGet包,搜索JWT,安装图下这个包
3. 在appsettings.json添加JWT加密需要的私钥,发布者等相关配置信息,私钥用户可以自定义。
私钥:SecretKey
发布者:Issuer
接收者:Audience
"Authentication": {
"SecretKey": "nadjhfgkadshgoihfkajhkjdhsfaidkuahfhdksjaghidshyaukfhdjks",
"Issuer": "www.adsfsadfasdf",
"Audience": "www.adsfsadfasdf"
}
4. 生成JWT,存放用户信息,上篇文章我们基本认识解析了JWT,JWT分为三部分:
- 标头(Header):有令牌的类型和所使用的签名算法,如HMAC、SHA256、RSA,用于加密Signature,使用Base64编码组成。
- 有效载荷(Payload):存放用户信息,用户id,权限等,不不放用户敏感的信息,如密码,使用Base64编码组成。
- 签名(Signature):使用编码后的header和payload
加上我们提供的一个密钥,使用header中指定的签名算法(HS256)进行签名加密。
using JWTDemo.Dtos;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace JWTDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
public readonly IConfiguration _configuration;
public AuthenticationController(IConfiguration configuration)
{
_configuration=configuration;
}
[HttpPost("login")]
public IActionResult Login([FromBody] LoginDto loginDto)
{
//1.验证用户账号密码是否正确,暂时忽略,因为我们是模拟登录
//2.生成JWT
//Header,选择签名算法
var signingAlogorithm = SecurityAlgorithms.HmacSha256;
//Payload,存放用户信息,下面我们放了一个用户id
var claims = new []
{
new Claim(JwtRegisteredClaimNames.Sub,"user_id")
};
//Signature
//取出私钥并以utf8编码字节输出
var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
//使用非对称算法对私钥进行加密
var signingKey = new SymmetricSecurityKey(secretByte);
//使用HmacSha256来验证加密后的私钥生成数字签名
var signingCredentials=new SigningCredentials(signingKey, signingAlogorithm);
//生成Token
var Token=new JwtSecurityToken(
issuer: _configuration["Authentication:Issuer"], //发布者
audience: _configuration["Authentication:Audience"], //接收者
claims: claims, //存放的用户信息
notBefore: DateTime.UtcNow, //发布时间
expires:DateTime.UtcNow.AddDays(1), //有效期设置为1天
signingCredentials //数字签名
);
//生成字符串token
var TokenStr=new JwtSecurityTokenHandler().WriteToken(Token);
return Ok(TokenStr);
}
}
}
取出用户信息用
//“user_id”键名
var id = HttpContext.User.Claims.First(c => c.Type == "user_id");
5. 启动项目,测试接口,生成token成功
6. 在Program.cs注入JWT身份认证服务,下面代码均有注释
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
//取出私钥
var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["Authentication:SecretKey"]);
options.TokenValidationParameters = new TokenValidationParameters()
{
//验证发布者
ValidateIssuer = true,
ValidIssuer = builder.Configuration["Authentication:Issuer"],
//验证接收者
ValidateAudience = true,
ValidAudience = builder.Configuration["Authentication:Audience"],
//验证是否过期
ValidateLifetime = true,
//验证私钥
IssuerSigningKey = new SymmetricSecurityKey(secretByte)
};
});
//添加jwt验证
app.UseAuthentication();
app.UseAuthorization();
7. 给api加上授权保护,新建一个测试api,在api上面添加[Authorize]
[HttpGet("test")]
[Authorize]
public IActionResult test()
{
return Ok("test");
}
8.测试接口
没登陆获取到Token,直接请求失败,返回401
登录一下获取到token加到Headers上注意bearer后面有个空格分开,才加上token:
KEY:Authorization
VALUE:bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyX2lkIiwibmJmIjoxNjQ5MzQ0MDY0LCJleHAiOjE2NDk0MzA0NjQsImlzcyI6Ind3dy5hZHNmc2FkZmFzZGYiLCJhdWQiOiJ3d3cuYWRzZnNhZGZhc2RmIn0.-yNVFtme3LzmAJFCcBSjN-DX7w_dZSpmGdrHlo7bXxc
请求成功:
9.登录成功后给用户添加权限
在之前登录生成JWT的api方法里,我们在JWT的Payload给用户添加一个权限名称信息,new Claim(ClaimTypes.Role,“admin”)
10.给api接口添加权限
[Authorize(Roles =“admin”)],权限为admin用户才能访问
[HttpGet("test")]
[Authorize(Roles ="admin")]
public IActionResult test()
{
return Ok("test");
}