十年河东,十年河西,莫欺少年穷

学无止境,精益求精

1、项目中引入jwt

2、创建token的实例代码如下:

2.1、所需的实体类

/// <summary>
/// POCO类,用来存储签发或者验证jwt时用到的信息
/// </summary>
public class TokenOptions
{
public static string Secret = "chenwolong_love_woman_2022";//私钥 至少16个字符

public static string Issuer = "webapi.cn";

public static string Audience = "WebApi";

public static int AccessExpiration = 180;//过期时间

}

2.2、创建Token

public dynamic UserLogin(string uname, string upwd)
{
var userinfo = new { uname = "陈卧龙", sex = "男", age = 30, userrole = new List<string>() { "admin", "staff" }, city = "苏州", love = "美女" };
var expiresTime = DateTime.Now.AddMinutes(TokenOptions.AccessExpiration);
var claims = new[]
{
new Claim(ClaimTypes.Name,uname),
new Claim(ClaimTypes.Role,ClaimTypes.Role ), //
new Claim(ClaimTypes.Actor,"wuan"),
new Claim(ClaimTypes.Country,"China"),
new Claim(ClaimTypes.Expired,"China"),
new Claim(ClaimTypes.UserData,JsonConvert.SerializeObject(userinfo))
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenOptions.Secret));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var jwtToken = new JwtSecurityToken(TokenOptions.Issuer, TokenOptions.Audience, claims, expires: expiresTime, signingCredentials: credentials);

var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
//加上 "Bearer " 是为了兼容swagger
return new { token = "Bearer "+ token, expiresTime = expiresTime.ToString("yyyy-MM-dd HH:mm:ss") };

}

3、jwt 中间件

3.1、所需的实体

public class CurrentUser
{
public string uname { get; set; }
public string sex { get; set; }
public int age { get; set; }
public List<string> userrole { get; set; } = new List<string>();
public string city { get; set; }
public string love { get; set; }
}

仔细看这个实体类,和我们创建token时定义的匿名变量是一致的

NetCore3.1  Json web token 中间件_ide

 

 3.2、中间件的编写

using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using wuanModel;

namespace wuanIotApi.Middlewares
{

public class JwtMiddlewares
{
private readonly RequestDelegate _next;

public JwtMiddlewares(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context)
{
context.Request.Headers.TryGetValue("Authorization", out var apiKeyHeaderValues);
if (apiKeyHeaderValues.Count > 0)
{
//这里是为了兼容swagger
var token = apiKeyHeaderValues.FirstOrDefault().Replace("Bearer ","");

AttachUserToContext(context, token);
}

await _next.Invoke(context);
}

private void AttachUserToContext(HttpContext context, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(TokenOptions.Secret); //获取到用于生成token的加密key

tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true, //是否验证Key SecurityKey
IssuerSigningKey = new SymmetricSecurityKey(key), //拿到SecurityKey
ValidateIssuer = false, //是否验证Issuer
ValidateAudience = false, //是否验证Audience
ValidateLifetime = true, //是否验证Token的失效时间
}, out SecurityToken validatedToken);

var jwtToken = (JwtSecurityToken)validatedToken;
//调试得知,ValidTo时间时区和北京时间相差8小时,通过这个时间,判断Token是否过期
var ValidTo = jwtToken.ValidTo.AddHours(8);
if (ValidTo < DateTime.Now)
{
return;
}
var userdata = jwtToken.Claims.Where(A => A.Type.Contains("userdata")).ToList().FirstOrDefault().Value;
//写入认证信息,方便业务类使用
var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim("userdata", userdata) });
Thread.CurrentPrincipal = new ClaimsPrincipal(claimsIdentity);

//将Token中解析出来的用户信息存入当前请求中
context.Items["userdata"] = Newtonsoft.Json.JsonConvert.DeserializeObject<CurrentUser>(userdata);
}
catch (Exception ex)
{
context.Items["userdata"] = null;
}
}
}
}

context.Items["userdata"]的使用

4、创建基础控制器

4.1,基础控制器

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using wuanCommon;
using wuanModel;

namespace wuanIotApi.Controllers
{
[Authorize]
[Route("api/V1/[controller]")]
[ApiExplorerSettings(GroupName = "V1")]
public class BaseController : Controller
{
public CurrentUser user = new CurrentUser();
public BaseController() { }
/// <summary>
/// 第2步执行基类构造函数
/// 第3步 执行父类的异步方法 异步方法 似乎可以和OnActionExecuting同时执行
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
return base.OnActionExecutionAsync(context, next);
}

/// <summary>
/// 第4步 执行OnActionExecuting方法
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!Request.Headers.TryGetValue("Authorization", out var apiKeyHeaderValues))
{
user =null;
}
else
{
user = (CurrentUser)this.HttpContext.Items["userdata"];
}
}

/// <summary>
/// 第五步执行基类Action
/// 第6步 Aciton执行完毕后 执行 OnActionExecuted
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(context);
}


}
}

4.2 ,继承自基础控制器的其他webapi控制器

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using wuanInterface;

namespace wuanIotApi.Controllers
{
public class UserController : BaseController
{
private readonly IUserService service;
public UserController(IUserService _service)
{
this.service = _service;
}
/// <summary>
/// 用户登录
/// </summary>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
[Route("UserLogin")]
public IActionResult UserLogin()
{
var result = service.UserLogin("", "");
return Ok(result);
}

[HttpPost]
[Route("TokenTest")]
public IActionResult TokenTest()
{
return Ok(user);
}
}
}

当带Token请求时,其中 TokenTest 会打印当前请求人的基本信息,也就是:陈卧龙  在苏州 喜欢美女  这些

@天才卧龙的博客