经历了很久,.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身份认证系统的更多相关文章

  1. ASP.NET Core系列:JWT身份认证

    1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...

  2. ASP.NET Core 3.0 gRPC 身份认证和授权

    一.开头聊骚 本文算是对于 ASP.NET Core 3.0 gRPC 研究性学习的最后一篇了,以后在实际使用中,可能会发一些经验之文.本文主要讲 ASP.NET Core 本身的认证授权和gRPC接 ...

  3. 关于ASP.Net Core Web及API身份认证的解决方案

    6月15日,在端午节前的最后一个工作日,想起有段日子没有写过文章了,倒有些荒疏了.今借夏日蒸蒸之气,偷得浮生半日悠闲.闲话就说到这里吧,提前祝大家端午愉快(屈原听了该不高兴了:))!.NetCore自 ...

  4. 介绍 ASP.NET Identity - ASP.NET 应用程序的成员身份认证系统

    ASP.NET Identity 是构建 ASP.NET web 应用程序的一种新的身份认证系统.ASP.NET Identity 可以让您的应用程序拥有登录功能,并可以轻松地自定义登录用户的相关数据 ...

  5. NET Core 2.0使用Cookie认证实现SSO单点登录

    NET Core 2.0使用Cookie认证实现SSO单点登录 之前写了一个使用ASP.NET MVC实现SSO登录的Demo,https://github.com/bidianqing/SSO.Sa ...

  6. ASP.NET Core的无状态身份认证框架IdentityServer4

    Identity Server 4是IdentityServer的最新版本,它是流行的OpenID Connect和OAuth Framework for .NET,为ASP.NET Core和.NE ...

  7. ASP.NET CORE中使用Cookie身份认证

    大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...

  8. 中国科学技术大学统一身份认证系统CAS

    CAS | Apereohttps://www.apereo.org/projects/cas 中国科学技术大学统一身份认证系统https://passport.ustc.edu.cn/login?s ...

  9. JWT 身份认证优缺点分析以及常见问题解决方案

    本文转载自:JWT 身份认证优缺点分析以及常见问题解决方案 Token 认证的优势 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势: 1.无状态 token ...

随机推荐

  1. 程序员转项目管理之考证PMP

    转行项目经历是IT人的出路之一,最近身边有好几个同事都在备考PMP,从个人未来职业发展来看,如果你有将来转行项目管理的想法,应该去尝试考一下PMP. PMP(Project Management Pr ...

  2. 终于解决了一个Win7 下 VS 编译的问题,困扰了我好几个月

    用 Win7 一年多了,一直在这个环境下编程,其他都挺好,就是有个问题非常恶心,在VS下编译经常出现进程正在使用,无法覆盖的错误,这个问题我记得博问中以前也有其他人遇到过,也没有解决掉.此问题困扰了我 ...

  3. 配置进程外Session

    配置进程外Session: (1)将服务器Session信息存储在进程外           <1> 首先,开启asp.net state 服务: 控制面板 -> 程序和功能 -&g ...

  4. Java-API:un-java.text.DecimalFormat

    ylbtech-Java-API:java.text.DecimalFormat 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部 0. https://docs. ...

  5. mybatis如何防止sql注入(1)

    sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如“or ‘1’=‘1’”这样的语句,有可能入侵参数校验不足的应用程序.所以在我们的应用中需要 ...

  6. java基础知识(15)----StringBuffer与StringBuilder

    StringBuffer字符串缓冲区: 构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符.特点:1:可以对字符串内容进行修改.2:是一个容器.3:是可变长度的.4:缓冲区中可以存储任意类型 ...

  7. 微信开发准备(一)--Maven仓库管理新建WEB项目

    转自:http://www.cuiyongzhi.com/post/13.html 在我们的项目开发中经常会遇到项目周期很长,项目依赖jar包特别多的情况,所以我们经常会在项目中引入Maven插件,建 ...

  8. linux 信号量之SIGNAL 0<转>

    我们可以使用kill -l查看所有的信号量解释,但是没有看到SIGNAL 0的解释. [root@testdb~]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) ...

  9. DAY17-Ajax

    Ajax准备知识:json 什么是json? 定义: JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式. 它基于 ECMAScript ( ...

  10. python操作excel的读写

    1.下载xlrd和xlwt pip install xlwd pip install xlrd pip install xlutils 2.读写操作(已存在的excel) #-*- coding:ut ...