添加NuGet引用

IdentityModel
Microsoft.AspNetCore.Authorization.JwtBearer

在appsettings.json中添加JwtBearer配置

"Authentication": {
"JwtBearer": {
"IsEnabled": "true",
"SecurityKey": "JWTStudyWebsite_DI20DXU3",
"Issuer": "JWTStudy",
"Audience": "JWTStudyWebsite"
}
}

创建JWT服务注册扩展

public static class JwtConfiguration
{
public static void AddJwtConfiguration(this IServiceCollection services, IConfiguration configuration)
{
if (bool.Parse(configuration["Authentication:JwtBearer:IsEnabled"]))
{
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = "JwtBearer";
options.DefaultChallengeScheme = "JwtBearer";
}).AddJwtBearer("JwtBearer", options =>
{
options.Audience = configuration["Authentication:JwtBearer:Audience"]; options.TokenValidationParameters = new TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.ASCII.GetBytes(configuration["Authentication:JwtBearer:SecurityKey"])), // Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = configuration["Authentication:JwtBearer:Issuer"], // Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = configuration["Authentication:JwtBearer:Audience"], // Validate the token expiry
ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here
ClockSkew = TimeSpan.Zero
};
});
}
}
}

在startup>ConfigureServices中注册服务

services.AddJwtConfiguration(Configuration);

创建AccessTokenController

说明:用户首次使用用户名和密码登录,生成AccessToken和RefreshToken,
其中AccessToken的有效时间为30分钟,RefreshToken的有效时间为60分钟。

可能的情况

  • AccessToken没有过期
  • AccessToken已过期,RefreshToken未过期
  • RefreshToken已过期

一、首先创建一个方法,用于生成AccessToken

private string GetAccessToken(SessionUser user)
{
var claims = new[]
{
new Claim(JwtClaimTypes.Id, user.Id.ToString()),
new Claim(JwtClaimTypes.Name, user.Name),
new Claim(JwtClaimTypes.Role, "user")
}; var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Authentication:JwtBearer:SecurityKey"]));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(
_configuration["Authentication:JwtBearer:Issuer"],
_configuration["Authentication:JwtBearer:Audience"],
claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: credentials
); return new JwtSecurityTokenHandler().WriteToken(token);
}

二、通过用户名密码获取AccessToken

[HttpPost]
public IActionResult Post([FromBody]LoginModel model)
{
if (!string.IsNullOrWhiteSpace(model.Account) && !string.IsNullOrWhiteSpace(model.Pw))
{
var user = new SessionUser
{
Id = 1,
Name = "admin",
Role = "user"
}; var refreshToken = Guid.NewGuid().ToString("N");
var refreshTokenExpiredTime = DateTime.Now.AddMinutes(60); var cacheKey = $"RefreshToken:{refreshToken}";
var cacheValue = JsonConvert.SerializeObject(user); _cache.SetString(cacheKey, cacheValue,
new DistributedCacheEntryOptions
{
AbsoluteExpiration = refreshTokenExpiredTime
}); return Ok(new
{
AccessToken = GetAccessToken(user),
Code = 200,
RefreshTokenExpired = DateTimeHelper.ConvertToLong(refreshTokenExpiredTime),
RefreshToken = refreshToken
});
} return Ok(new { Code = 0, Token = "" });
}

三、通过RefreshToken获取新的AccessToken

[Authorize]
[HttpPost("Refresh")]
public IActionResult Refresh(RefreshTokenRequest request)
{
var token = request.Token;
var cacheStr = _cache.GetString($"RefreshToken:{token}");
if (string.IsNullOrWhiteSpace(cacheStr))
{
return Ok(new
{
Code = 0,
Message = "Token不存在或已过期"
});
} var cacheUser = JsonConvert.DeserializeObject<SessionUser>(cacheStr);
var userId = User.Claims.First(c => c.Type == JwtClaimTypes.Id); if (userId == null || cacheUser.Id.ToString() != userId.Value)
{
return Ok(new
{
Code = 0,
Message = "用户不匹配"
});
} var refreshToken = Guid.NewGuid().ToString("N");
var cacheKey = $"RefreshToken:{refreshToken}";
var refreshTokenExpiredTime = DateTime.Now.AddMinutes(60); _cache.SetString(cacheKey, cacheStr, new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTime.Now.AddMinutes(30)
}); return Ok(new
{
AccessToken = GetAccessToken(cacheUser),
Code = 200,
RefreshTokenExpired = DateTimeHelper.ConvertToLong(refreshTokenExpiredTime),
RefreshToken = refreshToken
});
}

完整代码

public class LoginModel
{
[Required]
public string Account { get; set; } [Required]
public string Pw { get; set; }
} public class SessionUser
{
public int Id { get; set; } public string Name { get; set; } public string Role { get; set; }
}
public class DateTimeHelper
{
/// <summary>
/// DateTime转时间戳
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static long ConvertToLong(DateTime date)
{
var startTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Utc);
return (new DateTimeOffset(date).UtcTicks - startTime.Ticks) / 10000;
} /// <summary>
/// 时间戳转DateTime
/// </summary>
/// <param name="timestamp"></param>
/// <returns></returns>
public static DateTime ConvertToDateTime(long timestamp)
{
var startTime = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Local);
return startTime.Add(new TimeSpan(timestamp * 10000));
}
}
[Route("api/[controller]")]
[ApiController]
public class AccessTokenController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IDistributedCache _cache;
private readonly UserService _service; public AccessTokenController(IConfiguration configuration, IDistributedCache cache, UserService service)
{
_configuration = configuration;
_cache = cache;
_service = service;
} /// <summary>
/// 登录,获取后原来RefreshToken将失效。
/// AccessToken有效时间30分钟
/// RefreshToken有效时间60分钟
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
public ActionResult Post([FromBody]LoginModel model)
{
var result = _service.Login(model.Account, model.Pw);
if (result.Code != 200)
{
return Ok(new {Code = 0, Message = result.Message});
} var user = new SessionUser
{
Id = result.Body.Id,
Name = result.Body.NickName,
Role = "user"
}; var refreshToken = Guid.NewGuid().ToString("N");
var refreshTokenExpiredTime = DateTime.Today.AddDays(7); var cacheKey = $"RefreshToken:{refreshToken}";
var cacheValue = JsonConvert.SerializeObject(user); _cache.SetString(cacheKey, cacheValue,
new DistributedCacheEntryOptions
{
AbsoluteExpiration = refreshTokenExpiredTime
}); return Ok(new
{
AccessToken = GetAccessToken(user),
Code = 200,
RefreshTokenExpired = DateTimeHelper.ConvertToLong(refreshTokenExpiredTime),
RefreshToken = refreshToken
});
} /// <summary>
/// 刷新AccessToken
/// </summary>
/// <param name="request">刷新的请求 {"token": "refresh_token"}</param>
/// <returns></returns>
[Authorize]
[HttpPost("Refresh")]
public IActionResult Refresh(RefreshTokenRequest request)
{
var token = request.Token;
var cacheStr = _cache.GetString($"RefreshToken:{token}");
if (string.IsNullOrWhiteSpace(cacheStr))
{
return Ok(new
{
Code = 0,
Message = "Token不存在或已过期"
});
} var cacheUser = JsonConvert.DeserializeObject<SessionUser>(cacheStr);
var userId = User.Claims.First(c => c.Type == JwtClaimTypes.Id); if (userId == null || cacheUser.Id.ToString() != userId.Value)
{
return Ok(new
{
Code = 0,
Message = "用户不匹配"
});
} var refreshToken = Guid.NewGuid().ToString("N");
var cacheKey = $"RefreshToken:{refreshToken}";
var refreshTokenExpiredTime = DateTime.Today.AddDays(7); _cache.SetString(cacheKey, cacheStr, new DistributedCacheEntryOptions
{
AbsoluteExpiration = refreshTokenExpiredTime
}); return Ok(new
{
AccessToken = GetAccessToken(cacheUser),
Code = 200,
RefreshTokenExpired = DateTimeHelper.ConvertToLong(refreshTokenExpiredTime),
RefreshToken = refreshToken
});
} /// <summary>
/// 通过SessionUser获取AccessToken
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
private string GetAccessToken(SessionUser user)
{
var claims = new[]
{
new Claim(JwtClaimTypes.Id, user.Id.ToString()),
new Claim(JwtClaimTypes.Name, user.Name),
new Claim(JwtClaimTypes.Role, "user")
}; var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Authentication:JwtBearer:SecurityKey"]));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(
_configuration["Authentication:JwtBearer:Issuer"],
_configuration["Authentication:JwtBearer:Audience"],
claims,
expires: DateTime.Now.AddHours(2),
signingCredentials: credentials
); return new JwtSecurityTokenHandler().WriteToken(token);
} /// <summary>
/// 刷新AccessToken的请求
/// </summary>
public class RefreshTokenRequest
{
/// <summary>
/// RefreshToken,登录后获取
/// </summary>
public string Token { get; set; }
}
}

AspNetCore3.0 和 JWT的更多相关文章

  1. 在asp.net core2.1中添加中间件以扩展Swashbuckle.AspNetCore3.0支持简单的文档访问权限控制

    Swashbuckle.AspNetCore3.0 介绍 一个使用 ASP.NET Core 构建的 API 的 Swagger 工具.直接从您的路由,控制器和模型生成漂亮的 API 文档,包括用于探 ...

  2. Swashbuckle.AspNetCore3.0的二次封装与使用

    关于 Swashbuckle.AspNetCore3.0 一个使用 ASP.NET Core 构建的 API 的 Swagger 工具.直接从您的路由,控制器和模型生成漂亮的 API 文档,包括用于探 ...

  3. SpringBoot2.0+Shiro+JWT 整合

    SpringBoot2.0+Shiro+JWT 整合 JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息. 我们利用一定的编 ...

  4. ASP.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库

    目录 说明 一.定义角色.API.用户 二.添加自定义事件 三.注入授权服务和中间件 三.如何设置API的授权 四.添加登录颁发 Token 五.部分说明 六.验证 说明 ASP.NET Core 3 ...

  5. 在AspNetCore3.0中使用Autofac

    1. 引入Nuget包 Autofac Autofac.Extensions.DependencyInjection 2. 修改Program.cs 将默认ServiceProviderFactory ...

  6. oAuth2.0及jwt介绍

    oAuth2.0流程示意如下: 关于jwt介绍: 说明: 关于jwt简单说明一下,jwt即为json web token,是用来和服务端建立加密通信所使用的的一种“约定”,主要组成见上图即可.服务端一 ...

  7. SpringBoot2.0 整合 JWT 框架,解决Token跨域验证问题

    本文源码:GitHub·点这里 || GitEE·点这里 一.传统Session认证 1.认证过程 1.用户向服务器发送用户名和密码. 2.服务器验证后在当前对话(session)保存相关数据. 3. ...

  8. ASP.NET Core 6.0 添加 JWT 认证和授权

    序言 本文将分别介绍 Authentication(认证) 和 Authorization(授权). 并以简单的例子在 ASP.NET Core 6.0 的 WebAPI 中分别实现这两个功能. 相关 ...

  9. .NET core3.0 使用Jwt保护api

    摘要: 本文演示如何向有效用户提供jwt,以及如何在webapi中使用该token通过JwtBearerMiddleware中间件对用户进行身份认证. 认证和授权区别? 首先我们要弄清楚认证(Auth ...

随机推荐

  1. Python_爬虫小实例

    爬虫小实例 一.问题描述与分析 Q:查询某一只股票,在百度搜索页面的结果的个数以及搜索结果的变化. 分析: 搜索结果个数如下图: 搜索结果的变化:通过观察可以看到,每个一段时间搜索结果的个数是有所变化 ...

  2. kubernetes第九章--管理机密信息

  3. js中this指向的三种情况

    js中this指向的几种情况一.全局作用域或者普通函数自执行中this指向全局对象window,普通函数的自执行会进行预编译,然后预编译this的指向是window //全局作用域 console.l ...

  4. dpkg文件缺失问题

    sudo apt-get update 命中:1 http://security.ubuntu.com/ubuntu bionic-security InRelease         命中:2 ht ...

  5. go语言实现限流器

    本文:https://chai2010.cn/advanced-go-programming-book/ch5-web/ch5-06-ratelimit.html Ratelimit 服务流量限制 计 ...

  6. django学习记录1

    在看django的基础知识,还是按照以前一样来总结,还是晚上再统一总结好了,边看边总结好像效果不大. 第一部分是生成数据库,用python manage.migrate命令来生成django的基础架构 ...

  7. 剑指Offer(三十四):第一个只出现一次的字符

    剑指Offer(三十四):第一个只出现一次的字符 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net ...

  8. Nginx中获取真实ip地址

    location / { proxy_pass http://localhost; proxy_set_header Host $host; proxy_set_header X-Real-IP $r ...

  9. Python语言程序设计(3)--实例2-python蟒蛇绘制-turtle库

    1. 2. 3.了解turtle库 Turtle,也叫海龟渲染器,使用Turtle库画图也叫海龟作图.Turtle库是Python语言中一个很流行的绘制图像的函数库.海龟渲染器,和各种三维软件都有着良 ...

  10. 行为型模式(四) 观察者模式(Observer)

    一.动机(Motivate) "观察者模式"在现实生活中,实例其实是很多的,比如:八九十年代我们订阅的报纸,我们会定期收到报纸,因为我们订阅了.银行可以给储户发手机短信,也是&qu ...