.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 ...
随机推荐
- win32 获取本机网卡信息(MAC地址,IP地址等)
由于一个需求需要获取网卡的MAC地址,就搜了一下,大部分都是COPY来COPY去的一些代码,有很多甚至不能直接运行或有还有内存泄漏.自己查了一下MSDN然后封装了一下: 需要注意,一个机器可能有多个网 ...
- WebForm中创建树节点TreeNode
Tree: namespace ECTECH.NorthSJ.Web.SysData { public partial class testTree : BasePage { ; protected ...
- AngularJS:路由
ylbtech-AngularJS:路由 1.返回顶部 1. AngularJS 路由 本章节我们将为大家介绍 AngularJS 路由. AngularJS 路由允许我们通过不同的 URL 访问不同 ...
- Javascript ——Navigator对象
见 <Javascript 高级程序设计 第二版> P172 一.检测插件: 1.获取所有插件名称: 非IE浏览器:根据plugins数组, function getplugins() { ...
- SqlServer——判断对象是否存在
对以下对象判断是否存在:database.table.proc.触发器.临时表.索引.对于这些对象的判断是通过数据表 SysObjects来获得的. 一.基础知识 1.SysObjects系统表 对于 ...
- 问题:oracle select into;结果:oracle SELECT INTO 和 INSERT INTO SELECT 两种表复制语句详解
oracle SELECT INTO 和 INSERT INTO SELECT 两种表复制语句详解 (2011-07-08 08:59:47) 转载▼ 标签: it 分类: oracle 我们经常会遇 ...
- 部署和调优 1.1 nfs部署和优化-2
更改共享目录文件默认的所有者和所属组 已知道客户端有个user11用户 cat /etc/passwd user11:x:501:501::/home/user11:/bin/bash 服务端打开 v ...
- Android中Activity之间的数据传递
在开发中,我们经常涌用到Activity,那么既然用到了Activity,就一定免不了在两个或者多个Activity之间传递数据.这里我们先说一说原理,然后在看看代码和例子. 情况A:我们需要从Act ...
- css垂直居中方法(一)
第一种方法:首先用margin:0 auto实现水平居中,然后设置position:relative,设置top为50%(父元素高度的50%),然后设置margin-top:-150px(设置负值是因 ...
- js-tree坑
今天遇到一个js坑,一个页面,有两棵树,用同一个套参数初始化的,,,,当选择完另一个棵树之后,再操作另一颗树,不选择树节点,就会有错误出现,,,