.Net Core 2.1 JWT Bearer 的认证
起因
最近想要学习一下 .net core 2.1 相关的知识,即是因为工作需要亦是在微服务和 docker 化的今天不得不去了解了解 .net core。API 第一步即是安全,即为认证(Authentication)以及授权(Authorization)
Authentication 认证
这次项目中在公司第一次接触到了 Oauth2.0 认证 token,其中使用的type 是Bearer,还要其他的常用认证模式 Basic、Digest,Basic 是属于明文认证(明文传输用户账号密码 只是对信息做了 BASE64 编码),但是 Digest 是加密认证,更加安全。
而Bearer 则是伴随着 Oauth 兴起的较为标准的认证,认证失败的情况下会把我们导向401(Unauthorized,未授权)状态码,并在WWW-Authenticate头中添加如何进行验证的信息。
通过 Bearer 认证的标准方式如下:
通过在请求的 Header 中添加如下 Header(注意 Bearer 后必须跟一个空格)
Authorization:Bearer [Access_Token]
这里引用一下大佬对 Bearer 的好处总结原文地址
- CORS: cookies + CORS 并不能跨不同的域名。而Bearer验证在任何域名下都可以使用HTTP header头部来传输用户信息。
- 对移动端友好: 当你在一个原生平台(iOS, Android, WindowsPhone等)时,使用Cookie验证并不是一个好主意,因为你得和Cookie容器打交道,而使用Bearer验证则简单的多。
- CSRF: 因为Bearer验证不再依赖于cookies, 也就避免了跨站请求攻击。
- 标准:在Cookie认证中,用户未登录时,返回一个
302
到登录页面,这在非浏览器情况下很难处理,而Bearer验证则返回的是标准的401 challenge
JWT(JSON WEB TOKEN)
一直看到都说 JWT,我还以为是图形化界面(深受JAVA之毒害 ),这里是一种 Bearer Token 的编码方式,有三部分组成,每个部分由 .
隔开:
<first part>.<second part>.<third part>
这三部分如下:
- 头部(Header)
头部一般由alg(所使用的Hash 加密算法一般为 Hmac Sha256或者是 RSA)、type指的是 token 的传输和编码类型,我们这里为 JWT。把这以 BASE64 编码就成为了第一部分(<first part>
)
{
"alg":"HS256",
"type":"JWT"
} - 载荷(Payload)
注意,这部分是BASE64编码Not Safe!!
,不要保存一些敏感信息在这个位置
这部分存储了主要的用户信息以及认证信息,同样这部分也需要BASE64 编码成为第二部分(<second part>
),在代码中这部分是System.Security.ClaimsClaim
的一个实力化列表,其中可以包含如下的信息:
标准中注册声明:比如认证时间,过期时间,用户信息,发布者,订阅者等
公共的声明:这个是自定义的,可以添加一些业务上的信息,但是注意不要和标准(IANA JSON Web Token)重复,另外这个部分是可以解密的(BASE64 编码可对称解密),所以不要存储用户或者服务的敏感信息
私有的声明:在这里存放一些发布者和订阅者共同约定的一些声明,但是这个只是 BASE64 编码(对称解密),所以也不要存放敏感信息。
一个栗子
{ "iss": "lilibuy.com",
"iat": 1532588852,
"exp": 1533193652,
"aud": "lilibuy.com",
"sub": "891532752",
"nickname": "smilesb101",
"username": "123456",
"scopes": [ "admin", "user" ]
}
具体描述可以查看 - 签名(Signature)
这部分加密之后成为第三部分(<third part>
由于密钥是Service这边提供并且混入了前面的第一部分以及第二部分的值来混淆最终的签名值,所以会较为安全)
这部分存在的意义就是为了解决前面部分的不安全性(利用前面配置的 alg算法以及 SecurityKey–Service 自己提供>128/8(即16位以上的)密钥),这部分是在 Service 端加解密的,加密算法如下 :
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
SECREATE_KEY
)
实战一下
创建项目
一开始是创建项目,这个不多说了,创建一个 .net core 2.1 的 API 项目
添加 JWT 配置
修改 appsettings.json,添加如下节点,这里配置好了密钥用于JWT Token 的第三部分签名
"JWT":{"SecurityKey":"ABCDEFGHIJKLMNOPQRSTUVWXYZ1456789513"
},
修改 Startup.cs 注册 JWT
- 修改后的 Configure(IApplicationBuilder app, IHostingEnvironment env) 方法如下:
在这里添加了对验证的使用,注意调用UseAuthentication() 必须要在调用 UseMvc() 之前。
public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseHsts();}app.UseAuthentication();app.UseHttpsRedirection();app.UseMvc();}
- 修改后的 ConfigureServices(IServiceCollection services) 方法
这里添加了一个 验证的处理方法,并且使用 JwtBearer 作为验证的处理,
o.Events = new JwtBearerEvents(){OnMessageReceived = context =>{context.Token = context.Request.Query["access_token"];return Task.CompletedTask;}};
这个方法就是为了我们能够验证通过 Url 传递过来的 JWT Token,当然你也可以进行其他的一些定义,比如还要验证是否拥有其他Header,或者其他必要的参数。
options.TokenValidationParameters = new TokenValidationParameters{ValidateIssuer = true,ValidateAudience = true,ValidateLifetime = true,ValidateIssuerSigningKey = true,ValidIssuer = "lilibuy.com",ValidAudience = "lilibuy.com",IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:SecurityKey"]))};
这一个就是对验证的一些设置,比如是否验证发布者,订阅者,密钥,以及生命时间等等
增加认证以及 Token 给予
给 Controller 增加认证
注册了认证之后,认证并没有作用于 Controller 之上,所以我们需要通过给Controller 添加 AuthorizeAttribute 特性类标签来让认证在这个 Controller 上生效。
我们还是在示例工程的 ValuesController 上面动手脚,添加了认证后的代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;namespace LiliBuyMasterService.Controllers
{[Authorize][Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase{// GET api/values[HttpGet]public ActionResult<IEnumerable<string>> Get(){return new string[] { "value1", "value2" };}}
}
现在访问这个Controller 会提示 401
我们要如何取得认证呢?可以想得到我们现在还需要一个接口来检查认证信息以及返回认证的结果给用户使用
Token 给予
我们新建一个 OauthController,这个API Controller 类需要完成用户信息的比对以及如果比对结果显示这个是合法的用户,我们需要给用户返回 Token 信息。
修改后的 OauthController 如下
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using LiliBuyMasterService.Models.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860namespace LiliBuyMasterService.Controllers
{[AllowAnonymous][Route("api/[controller]")]public class OauthController : Controller{public IConfiguration Configuration { get; }public OauthController(IConfiguration configuration){Configuration = configuration;}[HttpPost("authenticate")]public IActionResult RequestToken([FromBody]TokenRequest request){if (request != null){//验证账号密码,这里只是为了demo,正式场景应该是与DB之类的数据源比对if ("smilesb101".Equals(request.UserName) && "123456".Equals(request.Password)){var claims = new[] {//加入用户的名称new Claim(ClaimTypes.Name,request.UserName)};var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:SecurityKey"]));var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var authTime = DateTime.UtcNow;var expiresAt = authTime.AddDays(7);var token = new JwtSecurityToken(issuer: "lilibuy.com",audience: "lilibuy.com",claims: claims,expires: expiresAt,signingCredentials: creds);return Ok(new{access_token = new JwtSecurityTokenHandler().WriteToken(token),token_type = "Bearer",profile = new{name = request.UserName,auth_time = new DateTimeOffset(authTime).ToUnixTimeSeconds(),expires_at = new DateTimeOffset(expiresAt).ToUnixTimeSeconds()}});}}return BadRequest("Could not verify username and password.Pls check your information.");}}
}
这里面的 AllowAnonymous 属性是说明这个不需要用户登录,
Return 里面的东西则是对我们具体的返回体的一个定义,至少包括token,其他信息可以具体和使用 API 或者根据业务约定。
我们来访问一下这个接口试一下,先试一个错误的用户信息吧
再来试一试正确的
这里可以看到我们已经拿到认证通过的信息了
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoic21pbGVzYjEwMSIsImV4cCI6MTUzMzM3MzEzMSwiaXNzIjoibGlsaWJ1eS5jb20iLCJhdWQiOiJsaWxpYnV5LmNvbSJ9._DEksb3er3z-4ePaCMoFUzk0PDBV-MW5VTevS7C5Fas",
"token_type": "Bearer",
"profile": {
"name": "smilesb101",
"auth_time": 1532768331,
"expires_at": 1533373131
}
}
我们在再把这个信息加入到对 ValuesController 的请求里面去,我们由于实现的是默认的认证方式,所以这里我们也通过标准的方式来修改我们的 GET 请求,在 Header中加入如下信息:
Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoic21pbGVzYjEwMSIsImV4cCI6MTUzMzM3MzEzMSwiaXNzIjoibGlsaWJ1eS5jb20iLCJhdWQiOiJsaWxpYnV5LmNvbSJ9._DEksb3er3z-4ePaCMoFUzk0PDBV-MW5VTevS7C5Fas
这里 Bearer+空格是一个固定的写法,我们这里使用的就是 Bearer 认证所以这里是 Bearer,添加了 Header 的请求如下
我们Send这个修改之后的请求,成功拿到数据:
到这里,一个基本的获取 Token 的认证就完成了。代码地址
.Net Core 2.1 JWT Bearer 的认证相关推荐
- AntDesign Pro + .NET Core 实现基于JWT的登录认证
很多同学说AgileConfig的UI实在是太丑了.我想想也是的,本来这个项目是我自己使用的,一开始甚至连UI都没有,全靠手动在数据库里修改数据.后来加上了UI也是使用了老掉牙的bootstrap3做 ...
- ASP.NET Core WebAPI JWT Bearer 认证失败返回自定义数据 Json
开发环境:ASP.NET Core Web API 目标框架:.NET Core 2.2 权限认证:JWT Bearer 提供者:成长的小猪 Jason Song 应用场景:当前我们给微信小程 ...
- ASP.NET Core WebAPI中使用JWT Bearer认证和授权
为什么是 JWT Bearer ASP.NET Core 在 Microsoft.AspNetCore.Authentication 下实现了一系列认证, 包含 Cookie, JwtBearer, ...
- 如何简单的在 ASP.NET Core 中集成 JWT 认证?
前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...
- 三分钟学会.NET Core Jwt 策略授权认证
一.前言 大家好我又回来了,前几天讲过一个关于Jwt的身份验证最简单的案例,但是功能还是不够强大,不适用于真正的项目,是的,在真正面对复杂而又苛刻的客户中,我们会不知所措,就现在需要将认证授权这一块也 ...
- SpringBoot+SpringSecurity前后端分离+Jwt的权限认证(改造记录)
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/zzzgd_666/article/details/96444829 前言 一般来说,我们用Spr ...
- Spring Security Oauth2 JWT 实现用户认证授权功能
Spring Security Oauth2 JWT 一 用户认证授权 1. 需求分析 1.1 用户认证与授权 什么是用户身份认证? 用户身份认证即用户去访问系统资源时系统要求验证用户的身份信息,身份 ...
- Spring Boot整合JWT实现用户认证
JWT实现用户认证 在介绍完JWT之后我们使用springboot整合JWT实现用户认证. 前后端分离使用JWT做用户认证(概述) JWT实现认证的原理 服务器在生成一个JWT之后会将这个JWT会以 ...
- SpringBoot+SpringSecurity前后端分离+Jwt的权限认证改造记录!
大家好,我是宝哥! 前言 一般来说,我们用SpringSecurity默认的话是前后端整在一起的,比如thymeleaf或者Freemarker,SpringSecurity还自带login登录页,还 ...
最新文章
- Raman Kazhamiakin
- HID接口设备-固件要求
- @retention注解作用_Spring 最核心的注解,都是干货!
- gsoap使用心得! (win32)
- 用VC++实现console程序显示彩色文本
- Cytoscape可视化物种分类树结构
- spring Boot环境下dubbo+zookeeper的一个基础讲解与示例
- java openSession和getCurrentSession的比较
- 实验四:Android 开发基础
- ioc中最基本的JAVA技术_Spring IOC 知识点总结
- [行业报告] 芒果发布8月份国内移动广告平台数据报告
- 关于Vue SSR不可不知的问题
- Lattice Diamond 3.12下载与安装(免费获取license.dat)
- 修复Pubwin EP置疑数据库
- Python爬取猫眼电影榜单评分,以及评论
- #500-7 [编程作业]3_4 念整数
- c++实现微妙级时间统计
- 自己创建一个小操作系统
- Springboot中上一个定时任务没执行完,是否会影响下一个定时任务执行分析及结论
- 数据库的这些你都知道吗?
热门文章
- 【专家访谈】测试专家 陈林钧 访谈记录整理汇总
- 再访洪小文:AI,誓不作恶
- 【多输入模型 Multiple-Dimension 数学原理分析以及源码详解 深度学习 Pytorch笔记 B站刘二大人 (6/10)】
- 【已修复】windows10更新:你的设备中缺少重要的安全和质量修复。
- [含文档+PPT+源码等]基于SSM个人财务记账账单收入支出统计管理系统[包运行成功]
- 大工19《计算机应用基础》在线测试2,大工19春《计算机应用基础》在线测试2 在Excel 2010中 存储数据的表格被称为...
- django 用户授权与许可
- Go Dumpling! 让导出数据更稳定丨TiDB 工具
- 短视频、直播平台——电商直播源码第三方SDK接入教程
- 中科蓝汛 GPIO操作