前言
在上一篇文章《.net core3.1项目部署到linux的docker》,向大家展示了一个简单的.net core api项目的部署过程,但是没有对接口的安全性过多的处理,相当于接口都是裸奔的情况,这是很危险的。所以我们对比进行升级一下,使用JWT来实现接口的认证。
什么是JWT
根据维基百科的定义,JSON WEB Token(JWT),是一种基于JSON的、用于在网络上声明某种主张的令牌(token),是目前最流行的接口认证方案。
简易JWT说明流程图
步骤说明:
- 客户端发送用户名密码信息到认证服务器获取 token;
- 客户端请求 API 获取数据时带上 token;
- 服务器端验证 token,合法则返回正确的数据。
深入了解
有一个网站叫:https://jwt.io/ ,我们在这个站点上对 Jwt 产生的 token 做验证:
从上图可以看出 Jwt 生产的 token 由三个部分组成:
- Header(红色):头
- Playload(紫色):负载
- Verify Sigantuer(蓝色):签名
这三个部分由英文的点进行拼接,内容结构为:Header.Payload.Signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header
头信息是一个json格式的数据
{"alg": "HS256","typ": "JWT"
}
- alg:表示加密的算法
- typ:表示 token 的类型
Playload
Playload 是 token 的主体内容部分,我们可以用来传递一些信息给客户端,比如过期时间就是通过 Playload 来进行传递的。 但因为默认情况下 Playload 的数据是明文的,所以敏感信息不要放在这里。
Verify Sigantuer
Verify Sigantuer 是对前面两个部分的签名,防止数据篡改。
开始使用JWT
下面我演示的截图都是在vs2019上面的操作
第一步,添加JWT包的引用
在.net core API项目中添加Microsoft.AspNetCore.Authentication.JwtBearer 包的引用
第二步,修改 Starup
- 在 ConfigureServices 方法中添加服务注册。
// jwt 认证services.AddAuthentication(options =>{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{
options.SaveToken = true;options.RequireHttpsMetadata = false;options.TokenValidationParameters = new TokenValidationParameters(){
ValidateIssuer = true,ValidateAudience = true,ValidAudience = "https://blog.csdn.net/shaojiayong",ValidIssuer = "https://blog.csdn.net/shaojiayong",IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecureKeySecureKeySecureKeySecureKeySecureKeySecureKey"))};});
- Configure 配置认证中间件
app.UseAuthentication();//认证中间件
第三步,创建一个token
- 添加一个登录model命名为LoginInput
public class LoginInput{
public string Username {
get; set; }public string Password {
get; set; }}
- 添加一个认证控制器命名为AuthenticateController
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using TestAPI.Model;namespace TestAPI.Controllers
{
[Route("api/[controller]")][ApiController]public class AuthenticateController : ControllerBase{
[HttpPost][Route("login")]public IActionResult Login([FromBody] LoginInput input){
//从数据库验证用户名,密码 //验证通过 否则 返回Unauthorized//创建claimvar authClaims = new[] {
new Claim(JwtRegisteredClaimNames.Sub,input.Username),new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())};IdentityModelEventSource.ShowPII = true;//签名秘钥 可以放到json文件中var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecureKeySecureKeySecureKeySecureKeySecureKeySecureKey"));var token = new JwtSecurityToken(issuer: "https://blog.csdn.net/shaojiayong",audience: "https://blog.csdn.net/shaojiayong",expires: DateTime.Now.AddHours(2),claims: authClaims,signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256));//返回token和过期时间return Ok(new{
token = new JwtSecurityTokenHandler().WriteToken(token),expiration = token.ValidTo});}}
}
第四步,控制器添加个Authorize标签
[Authorize][Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase