在.NET Core中使用Jwt对API进行认证
在.NET Core中想给API进行安全认证,最简单的无非就是Jwt,悠然记得一年前写的Jwt Demo,现在拿回来改成.NET Core的,但是在编码上的改变并不大,因为Jwt已经足够强大了。在项目中分为 DotNetCore_Jwt_Server 以及 DotNetCore_Jwt_Client ,从名字就可以看出来是啥意思,博客园高手云集,我就不多诉说,这篇博客就当是一篇记录。
当然本案例是Server&Client双项目,如果你要合成自己发证的形式,那你就自己改下代码玩。
在Server层都会有分发Token的服务,在其中做了用户密码判断,随后根据 Claim 生成 jwtToken 的操作。
其生成Token的服务代码:
namespace DotNetCore_Jwt_Server.Services
{
public interface ITokenService
{
string GetToken(User user);
}
public class TokenService : ITokenService
{
private readonly JwtSetting _jwtSetting;
public TokenService(IOptions<JwtSetting> option)
{
_jwtSetting = option.Value;
}
public string GetToken(User user)
{
//创建用户身份标识,可按需要添加更多信息
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("id", user.Id.ToString(), ClaimValueTypes.Integer32),
new Claim("name", user.Name),
new Claim("admin", user.IsAdmin.ToString(),ClaimValueTypes.Boolean)
}; //创建令牌
var token = new JwtSecurityToken(
issuer: _jwtSetting.Issuer,
audience: _jwtSetting.Audience,
signingCredentials: _jwtSetting.Credentials,
claims: claims,
notBefore: DateTime.Now,
expires: DateTime.Now.AddSeconds(_jwtSetting.ExpireSeconds)
);
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
return jwtToken;
}
}
}
在获取Token中我们依赖注入服务到控制器中,随后依赖它进行认证并且分发Token,
public class ValuesController : ControllerBase
{
private readonly IUserService _userService;
private readonly ITokenService _tokenService; public ValuesController(IUserService userService,
ITokenService tokenService)
{
_userService = userService;
_tokenService = tokenService;
}
[HttpGet]
public async Task<string> Get()
{
await Task.CompletedTask;
return "Welcome the Json Web Token Solucation!";
}
[HttpGet("getToken")]
public async Task<string> GetTokenAsync(string name, string password)
{
var user = await _userService.LoginAsync(name, password);
if (user == null)
return "Login Failed"; var token = _tokenService.GetToken(user);
var response = new
{
Status = true,
Token = token,
Type = "Bearer"
};
return JsonConvert.SerializeObject(response);
}
}
随后,我们又在项目配置文件中填写了几个字段,相关备注已注释,但值得说明的是有位朋友问我,服务器端生成的Token不需要保存吗,比如Redis或者是Session,其实Jwt Token是无状态的,他们之间的对比第一个是你的token解密出来的信息正确与否,第二部则是看看你 SecurityKey 是否正确,就这样他们的认证才会得出结果。
"JwtSetting": {
"SecurityKey": "d0ecd23c-dfdb-4005-a2ea-0fea210c858a", // 密钥
"Issuer": "jwtIssuertest", // 颁发者
"Audience": "jwtAudiencetest", // 接收者
"ExpireSeconds": // 过期时间
}
随后我们需要DI两个接口以及初始化设置相关字段。
public void ConfigureServices(IServiceCollection services)
{
services.Configure<JwtSetting>(Configuration.GetSection("JwtSetting"));
services.AddScoped<IUserService, UserService>();
services.AddScoped<ITokenService, TokenService>();
services.AddControllers();
}
在Client中,我一般会创建一个中间件用于接受认证结果,AspNetCore Jwt 源码中给我们提供了中间件,我们在进一步扩展,其源码定义如下:
/// <summary>
/// Extension methods to expose Authentication on HttpContext.
/// </summary>
public static class AuthenticationHttpContextExtensions
{/// <summary>
/// Extension method for authenticate.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/> context.</param>
/// <param name="scheme">The name of the authentication scheme.</param>
/// <returns>The <see cref="AuthenticateResult"/>.</returns>
public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context, string scheme) =>
context.RequestServices.GetRequiredService<IAuthenticationService>().AuthenticateAsync(context, scheme);
}
其该扩展会返回一个 AuthenticateResult 类型的结果,其定义部分是这样的,我们就可以将计就计,给他来个连环套。

连环套直接接受 httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme) 返回回来的值,随后进行判断返回相应的Http响应码。
public class AuthMiddleware
{
private readonly RequestDelegate _next; public AuthMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
var result = await httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
if (!result.Succeeded)
{
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await httpContext.Response.WriteAsync("Authorize error");
}
else
{
httpContext.User = result.Principal;
await _next.Invoke(httpContext);
}
}
}
当然你也得在Client中添加认证的一些设置,它和Server端的 IssuerSigningKey 一定要对应,否则认证失败。
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddScoped<IIdentityService, IdentityService>();
var jwtSetting = new JwtSetting();
Configuration.Bind("JwtSetting", jwtSetting); services.AddCors(options =>
{
options.AddPolicy("any", builder =>
{
builder.AllowAnyOrigin() //允许任何来源的主机访问
.AllowAnyMethod()
.AllowAnyHeader(); });
}); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = jwtSetting.Issuer,
ValidAudience = jwtSetting.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.SecurityKey)),
默认 300s
ClockSkew = TimeSpan.Zero
};
});
services.AddControllers();
}
随后,你就可以编写带需认证才可以访问的API了,如果认证失败则会返回401的错误响应。
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IIdentityService _identityService;
public ValuesController(IIdentityService identityService)
{
_identityService = identityService;
}
[HttpGet]
[Authorize]
public async Task<string> Get()
{
await Task.CompletedTask;
return $"{_identityService.GetUserId()}:{_identityService.GetUserName()}";
}
值得一提的是,我们可以根据 IHttpContextAccessor 以来注入到我们的Service或者Api中,它是一个当前请求的认证信息上下文,这将有利于你获取用户信息去做该做的事情。
public class IdentityService : IIdentityService
{
private readonly IHttpContextAccessor _context;
public IdentityService(IHttpContextAccessor context)
{
_context = context;
}
public int GetUserId()
{
var nameId = _context.HttpContext.User.FindFirst("id"); return nameId != null ? Convert.ToInt32(nameId.Value) : ;
}
public string GetUserName()
{
return _context.HttpContext.User.FindFirst("name")?.Value;
}
}
在源码中该类的定义如下,实际上我们可以看到只不过是判断了当前的http上下文吧,所以我们得出,如果认证失败,上下本信息也是空的。
public class HttpContextAccessor : IHttpContextAccessor
{
private static AsyncLocal<HttpContextHolder> _httpContextCurrent = new AsyncLocal<HttpContextHolder>(); public HttpContext HttpContext
{
get
{
return _httpContextCurrent.Value?.Context;
}
set
{
var holder = _httpContextCurrent.Value;
if (holder != null)
{
// Clear current HttpContext trapped in the AsyncLocals, as its done.
holder.Context = null;
} if (value != null)
{
// Use an object indirection to hold the HttpContext in the AsyncLocal,
// so it can be cleared in all ExecutionContexts when its cleared.
_httpContextCurrent.Value = new HttpContextHolder { Context = value };
}
}
} private class HttpContextHolder
{
public HttpContext Context;
}
}
如果要通过js来测试代码,您可以添加请求头来进行认证,beforeSend是在请求之前的事件。
beforeSend : function(request) {
request.setRequestHeader("Authorization", sessionStorage.getItem("Authorization"));
}
好了,今天就说到这,代码地址在https://github.com/zaranetCore/DotNetCore_Jwt 中。

在.NET Core中使用Jwt对API进行认证的更多相关文章
- 如何简单的在 ASP.NET Core 中集成 JWT 认证?
前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...
- .net core中使用jwt进行认证
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息.由于此信息是经过数字签名的,因此可以被验证和信任 ...
- 如何在ASP.NET Core中实现一个基础的身份认证
注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...
- [转]如何在ASP.NET Core中实现一个基础的身份认证
本文转自:http://www.cnblogs.com/onecodeonescript/p/6015512.html 注:本文提到的代码示例下载地址> How to achieve a bas ...
- 如何设计出和 ASP.NET Core 中 Middleware 一样的 API 方法?
由于笔者时间有限,无法写更多的说明文本,且主要是自己用来记录学习点滴,请谅解,下面直接贴代码了(代码中有一些说明): 01-不好的设计 代码: using System; namespace Desi ...
- spring boot 2 集成JWT实现api接口认证
JSON Web Token(JWT)是目前流行的跨域身份验证解决方案.官网:https://jwt.io/本文使用spring boot 2 集成JWT实现api接口验证. 一.JWT的数据结构 J ...
- ASP.NET Core 3.0 WebApi中使用Swagger生成API文档简介
参考地址,官网:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view ...
- EF Core中通过Fluent API完成对表的配置
EF Core中通过Fluent API完成对表的配置 设置实体在数据库中的表名 通过ToTable可以为数据模型在数据库中自定义表名,如果不配置,则表名为模型名的复数形式 public class ...
- ASP.NET Core系列:JWT身份认证
1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...
随机推荐
- [UWP]使用GetAlphaMask和ContainerVisual制作长阴影(Long Shadow)
1. 什么是长阴影 前几年扁平化设计(Flat Design)十分流行,后来在扁平化的基础上又流行起了长阴影(Long Shadow).长阴影其实就是扩展了对象的投影,感觉是一种光线照射下的影子,通常 ...
- Rest_Framework之认证、权限、频率组件源码剖析
一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...
- Life is short, I love Python~!
python学习目录 一:计算机基础 计算机基础 二:python基础 python基础 三:函数 函数 内置函数匿名函数 迭代器生成器 四:文件处理&异常 文件处理 异常处理 五:模块 常用 ...
- Java连接MySQL简单步骤及常见问题解析
这篇文章跟读者们介绍Java语言如何连接到MySQL数据库相关操作,及FAQ(Frequently Asked Questions)介绍. 选择工具和准备数据集 IDE:Eclipse 数据库:使用的 ...
- Java自动化测试框架-07 - TestNG之Factory篇 - 欢快畅游梦幻工厂(详细教程)
简介 最近忙着装修博客园,没时间更新文章,今天终于抽出时间把上次写的一半的文章给写完了,新的博客园风格,希望大家喜欢.今天继续介绍testng的相关知识--工厂. 工厂允许你动态的创建测试.例如,假设 ...
- mysql分组和去重同时使用
这是我的数据结构: 这是我的统计SQL
- 20190820 Tue 集训总结&NOIP模拟 27
低谷度过了? 但是skyh阿卡了,还是反衬出我的辣鸡. T1知道要sort,却忘了判重,正解不如暴力分高,555. T2成功化出正解柿子,然后化过头了,化出了无法DP的柿子. 果然不够强,大神们一眼就 ...
- 【ASP.NET Core学习】Entity Framework Core
这里介绍在ASP.NET Core中使用EF Core,这里数据库选的是Sql Server 如何使用Sql Server 添加模型 && 数据库迁移 查询数据 保存数据 如何使用Sq ...
- 股票交易——单调队列优化DP
题目描述 思路 蒟蒻还是太弱了,,就想到半个方程就GG了,至于什么单调队列就更想不到了. $f[i][j]$表示第$i天有j$张股票的最大收益. 那么有四种选择: 不买股票:$f[i][j]=max( ...
- MySQL系列:一句SQL,MySQL是怎么工作的?
对于MySQL而言,其实分为客户端与服务端. 服务端,就是MySQL应用,当我们使用net start mysql命令启动的服务,其实就是启动了MySQL的服务端. 客户端,负责发送请求到服务端并从服 ...