.net core 2.0 jwt身份认证系统
经历了很久,.net core 2.0 终于发布了!
之前一直用的core 1.1,升级了2.0后发现认证的机制(Auth)发生了比较大的变化,在1.1中认证配置是在Configure中完成,而在2.0中,认证配置则是在ConfigureServices中完成,刚好对调了一下。
话不多说,直接看代码
1.ConfigureServices中的认证配置
var audienceConfig = Configuration.GetSection("Audience");
var symmetricKeyAsBase64 = audienceConfig["Secret"];
var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
var signingKey = new SymmetricSecurityKey(keyByteArray); var tokenValidationParameters = new TokenValidationParameters
{ // The signing key must match!
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey, // Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = audienceConfig["Issuer"], // Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = audienceConfig["Audience"], // Validate the token expiry
ValidateLifetime = true, ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
//不使用https
//o.RequireHttpsMetadata = false;
o.TokenValidationParameters = tokenValidationParameters;
});
贴上appsettings.json的内容
"Audience": {
"Secret": "Y2F0Y2yhciUyMHdvbmclMFWfsaZlJTIwLm5ldA==",
"Issuer": "test",
"Audience": "test"
}
2. Configure中使用认证,这里我扩展了UseAuthentication的方法。
(1)先定义一个TokenProviderOptions类
public class TokenProviderOptions
{
/// <summary>
/// 请求路径
/// </summary>
public string Path { get; set; } = "/Api/Token"; public string Issuer { get; set; } public string Audience { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public TimeSpan Expiration { get; set; } = TimeSpan.FromMinutes(); public SigningCredentials SigningCredentials { get; set; }
}
(2)定义一个TokenProviderExtensions类扩展UseAuthentication方法
public static class TokenProviderExtensions
{
public static IApplicationBuilder UseAuthentication(this IApplicationBuilder app, TokenProviderOptions options)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<TokenProviderMiddleware>(Options.Create(options));
}
}
至于为什么UseAuthentication为什么长这样的,可以看https://github.com/aspnet/Security/blob/99aa3bd35dd5fbe46a93eef8a2c8ab1f9fe8d05b/src/Microsoft.AspNetCore.Authentication/AuthAppBuilderExtensions.cs源代码
(3)写了TokenProviderMiddleware类来代替AuthenticationMiddleware
public class TokenProviderMiddleware
{
private readonly RequestDelegate _next;
private readonly TokenProviderOptions _options;
private readonly IUserService _service;
public TokenProviderMiddleware(
RequestDelegate next,
IOptions<TokenProviderOptions> options, IAuthenticationSchemeProvider schemes)
{
_next = next;
_options = options.Value;
Schemes = schemes;
}
public IAuthenticationSchemeProvider Schemes { get; set; } /// <summary>
/// invoke the middleware
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task Invoke(HttpContext context,IUserServcice service)
{
_sercice=service;
//
context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
{
OriginalPath = context.Request.Path,
OriginalPathBase = context.Request.PathBase
});
//获取默认Scheme(或者AuthorizeAttribute指定的Scheme)的AuthenticationHandler
var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler;
if (handler != null && await handler.HandleRequestAsync())
{
return;
}
}
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await context.AuthenticateAsync(defaultAuthenticate.Name);
if (result?.Principal != null)
{
context.User = result.Principal;
}
}
// if (!context.Request.Path.Equals(_options.Path, StringComparison.Ordinal))
{
await _next(context);
return;
}
// Request must be POST with Content-Type: application/x-www-form-urlencoded
if (!context.Request.Method.Equals("POST")
|| !context.Request.HasFormContentType)
{
await ReturnBadRequest(context);
return;
} await GenerateAuthorizedResult(context);
} /// <summary>
/// 验证结果并得到token
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private async Task GenerateAuthorizedResult(HttpContext context)
{
var username = context.Request.Form["username"];
var password = context.Request.Form["password"]; var identity = await GetIdentity(username, password);
if (identity == null)
{
await ReturnBadRequest(context);
return;
} // Serialize and return the response
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(GetJwt(username));
} /// <summary>
/// 验证用户
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
private Task<ClaimsIdentity> GetIdentity(string username, string password)
{
var isValidated = _service.Auth(username,password); if (isValidated)
{
return Task.FromResult(new ClaimsIdentity(new System.Security.Principal.GenericIdentity(username, "Token"), new Claim[] { })); }
return Task.FromResult<ClaimsIdentity>(null);
} /// <summary>
/// return the bad request (200)
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private async Task ReturnBadRequest(HttpContext context)
{
context.Response.StatusCode = ;
await context.Response.WriteAsync(JsonConvert.SerializeObject(new
{
Status = false,
Message = "认证失败"
}));
} /// <summary>
/// get the jwt
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
private string GetJwt(string username)
{
var now = DateTime.UtcNow; var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(),
ClaimValueTypes.Integer64),
//用户名
new Claim(ClaimTypes.Name,username),
//角色
new Claim(ClaimTypes.Role,"a")
}; var jwt = new JwtSecurityToken(
issuer: _options.Issuer,
audience: _options.Audience,
claims: claims,
notBefore: now,
expires: now.Add(_options.Expiration),
signingCredentials:_options.SigningCredentials
);
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); var response = new
{
Status=true,
access_token = encodedJwt,
expires_in = (int)_options.Expiration.TotalSeconds,
token_type = "Bearer"
};
return JsonConvert.SerializeObject(response, new JsonSerializerSettings { Formatting = Formatting.Indented });
} }
(4)最后Configure中使用认证
var audienceConfig = Configuration.GetSection("Audience");
var symmetricKeyAsBase64 = audienceConfig["Secret"];
var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
var signingKey = new SymmetricSecurityKey(keyByteArray);
var SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
app.UseAuthentication(new TokenProviderOptions
{
Audience = audienceConfig["Audience"],
Issuer = audienceConfig["Issuer"],
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
});
3.最后的测试
.net core 2.0 jwt身份认证系统的更多相关文章
- ASP.NET Core系列:JWT身份认证
1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...
- ASP.NET Core 3.0 gRPC 身份认证和授权
一.开头聊骚 本文算是对于 ASP.NET Core 3.0 gRPC 研究性学习的最后一篇了,以后在实际使用中,可能会发一些经验之文.本文主要讲 ASP.NET Core 本身的认证授权和gRPC接 ...
- 关于ASP.Net Core Web及API身份认证的解决方案
6月15日,在端午节前的最后一个工作日,想起有段日子没有写过文章了,倒有些荒疏了.今借夏日蒸蒸之气,偷得浮生半日悠闲.闲话就说到这里吧,提前祝大家端午愉快(屈原听了该不高兴了:))!.NetCore自 ...
- 介绍 ASP.NET Identity - ASP.NET 应用程序的成员身份认证系统
ASP.NET Identity 是构建 ASP.NET web 应用程序的一种新的身份认证系统.ASP.NET Identity 可以让您的应用程序拥有登录功能,并可以轻松地自定义登录用户的相关数据 ...
- NET Core 2.0使用Cookie认证实现SSO单点登录
NET Core 2.0使用Cookie认证实现SSO单点登录 之前写了一个使用ASP.NET MVC实现SSO登录的Demo,https://github.com/bidianqing/SSO.Sa ...
- ASP.NET Core的无状态身份认证框架IdentityServer4
Identity Server 4是IdentityServer的最新版本,它是流行的OpenID Connect和OAuth Framework for .NET,为ASP.NET Core和.NE ...
- ASP.NET CORE中使用Cookie身份认证
大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...
- 中国科学技术大学统一身份认证系统CAS
CAS | Apereohttps://www.apereo.org/projects/cas 中国科学技术大学统一身份认证系统https://passport.ustc.edu.cn/login?s ...
- JWT 身份认证优缺点分析以及常见问题解决方案
本文转载自:JWT 身份认证优缺点分析以及常见问题解决方案 Token 认证的优势 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势: 1.无状态 token ...
随机推荐
- 门禁 IC卡 ID 卡 RFID 手环 NFC 银行卡 手机模拟门禁
门禁 IC卡 ID 卡 RFID 手环 NFC 银行卡 手机模拟门禁 原因 最近给公司换了一个门禁. 旧的门禁按键面板已经破了. 不支持我的手环. 按了密码后竟然要按 #. 相关信息 查了资料记录一下 ...
- LeetCode第五题:Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- Windows Server 2008 修改系统的SID
故事背景:用VMware搭建了几个操作系统相同的虚拟机.安装成功一台后,直接拷贝已经生成的VMDK文件来构建其它的虚拟机. 一般情况下,如果复制的各个虚拟机只是单独使用,并且这些虚拟机不加入到域(Ac ...
- Oracle AWR,SQL_TRACE,10046,DBMS_PROFILER 等使用
Oracle AWR,SQL_TRACE,10046,DBMS_PROFILER 等使用 1 AWR 工具的使用及优化 1 10g默认安装 select * from dba_hist_wr_cont ...
- [置顶]
制作开机LOGO就是这么简单!
转自: http://mp.weixin.qq.com/s?__biz=MzAxNTAyOTczMw==&mid=2649328522&idx=1&sn=64107695fef ...
- Oracle 多表查询(1)
一.基本概念 多表查询的语法如下: SELECT [DISTINCT] * | 字段 [别名] [,字段 [别名] ,…]FROM 表名称 [别名], [表名称 [别名] ,…][WHERE 条件(S ...
- UML在软件开发中各个阶段的作用和意义
经典的软件工程思想将软件开发分成5个阶段:需求分析,系统分析与设计,系统实现,测试及维护五个阶段. 之所以如此,是因为软件开发中饣含了物和人的因素,存在着很大的不确定性,这使得软件工程不可能像理想的, ...
- spring读取classpath目录下的配置文件通过表达式去注入属性值.txt
spring读取配置文件: 1. spring加载配置文件: <context:property-placeholder location="classpath:config/syst ...
- windows安装和配置JDK
安装完JDK后配置环境变量 计算机→属性→高级系统设置→高级→环境变量 系统变量→新建 JAVA_HOME 变量 . 变量值填写jdk的安装目录(本人是 E:\Java\jdk1.7.0) ...
- JAVA中的垃圾回收机制以及其在android开发中的作用
http://blog.csdn.net/xieqibao/article/details/6707519 这篇文章概述了JAVA中运行时数据的结构,以及垃圾回收机制的作用.在后半部分,描述了如何检测 ...