最近,团队的小伙伴们在做项目时,需要用到JWT认证。遂根据自己的经验,整理成了这篇文章,用来帮助理清JWT认证的原理和代码编写操作。
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JWT是什么,看上面这段网上抄来的话。
关于JWT以及优缺点,网上有很多详细的说法,我这儿就不重复了。
我们只需要知道以下的事实:
在一般的系统中,我们有时候会做个用户登录。用户登录完成进到系统后,需要根据用户的权限,来控制一些功能可用,而另一些功能不可用。
在SOA/AOP架构中,做为最重要的API端,其实也需要有类似登录或认证的内容,用来区分哪些用户可以使用某个API,哪些用户不行。
同时,我们希望这个登录或类似登录的过程,只发生在一个固定位置。这样,在我们写代码时,建立好这样一个过程后,在我们后边写代码时,简单引用即可,而不需要每个API程序都开发一次认证。这个需求,其实就是OAuth的由来。
最重要的是,这样的代码写出来,显得高大上。
下面进入正题。
认证这个操作,就像我们最近的日子。
首先,我们要有一个出入证,或者绿码。这个证,我们称作令牌(Token)。我们去领这个证,这个操作称为发行(Issue)。
我们拿着这个证,去到一个地方。有专人会检查这个证,这称为用户身份验证(Authentication)。验证通过放行,称为授权(Authorization),验证不通过,叫作未授权错误(Unauthorized)。
如果这个证过期了,你就需要去重新办一个证。这个过程叫做刷新(RefreshToken)。
简言之,这就是认证的全部流程。
下面,我用一个Demo项目,来逐步完成这个过程。
这个Demo的开发环境是:Mac + VS Code + Dotnet Core 3.1.2。
$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.201
Commit: b1768b4ae7
Runtime Environment:
OS Name: Mac OS X
OS Version: 10.15
OS Platform: Darwin
RID: osx.10.15-x64
Base Path: /usr/local/share/dotnet/sdk/3.1.201/
Host (useful for support):
Version: 3.1.3
Commit: 4a9f85e9f8
.NET Core SDKs installed:
3.1.201 [/usr/local/share/dotnet/sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.App 3.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
首先,在这个环境下建立工程:
% dotnet new sln -o demo
The template "Solution File" was created successfully.
2.用Webapi模板创建项目
% cd demo
% dotnet new webapi -o demo
The template "ASP.NET Core Web API" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on demo/demo.csproj...
Restore completed in 179.13 ms for demo/demo.csproj.
Restore succeeded.
3.把Demo项目加到Solution中
% dotnet sln add demo/demo.csproj
Project `demo/demo.csproj` added to the solution.
4.安装Swagger(这步非必须,我习惯用Swagger,不习惯用Postman)
% dotnet add package Swashbuckle.AspNetCore
log : Restore completed in 2.75 sec for demo/demo.csproj.
5.安装JWT认证支持库(必须引入)
% dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
log : Restore completed in 3.09 sec for demo/demo.csproj.
五步做完,基础项目就建完了。
看一下整个的目录结构:
% tree .
.
├── demo
│ ├── Controllers
│ │ └── WeatherForecastController.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Startup.cs
│ ├── WeatherForecast.cs
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── demo.csproj
│ └── obj
│ ├── demo.csproj.nuget.dgspec.json
│ ├── demo.csproj.nuget.g.props
│ ├── demo.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
└── demo.sln
6.在Startup.cs中补充代码,以启用Swagger
在ConfigureServices方法中加入以下代码:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo", Version = "V1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "",
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
在Configure方法中加入以下代码
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Demo V1");
});
关于Swagger的详细配置,这里不做说明,留着以后写。
签发Token是认证的第一步。
用户进到系统,在验证用户帐号密码后,需要根据用户的数据,把Token返回给用户。
这个过程其实跟认证没什么关系,只是一个普通的API功能。
using System;
namespace demo.DTOModels
{
public class LoginRequestDTO
{
public string username { get; set; }
public string password { get; set; }
}
}
2.创建一个控制器AuthenticationController,并在控制器里创建一个API方法RequestToken。
using Microsoft.AspNetCore.Mvc;
using demo.DTOModels;
namespace demo.Controllers
{
public class AuthenticationController : ControllerBase
{
[HttpPost, Route("requesttoken")]
public ActionResult RequestToken([FromBody] LoginRequestDTO request)
{
//这儿待完善
return Ok();
}
}
}
3.生成JWT Token需要预设一些参数。我们在appsetting.json里先设置好。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"tokenParameter": {
"secret": "123456123456123456",
"issuer": "WangPlus",
"accessExpiration": 120,
"refreshExpiration": 1440
}
}
这里,tokenParameter节是我们设置的参数。一般来说,是这几个:
secret: JWT加密的密钥。现在主流用SHA256加密,需要256位以上的密钥,unicode是16个字符以上,尽量复杂一些。密钥泄露,Token就会被破解,所以,你懂的。
issuer: 签发人的名称,如果没人注意,你可以把大名写在上面。
accessExpiration: Token的有效分钟数。过了这个时间,这个Token会过期。
refreshExpiration: refreshToken的有效分钟数。过了这个时间,用户需要重新登录。
Token过期后,可以让用户重新登录认证拿Token。但这个方式会比较Low。高大上的方式是签发Token的时候,同时也签发一个refreshToken给用户。用户Token过期后,可以拿refreshToken去申请新的Token,同时刷新refreshToken。如果用户长时间未使用系统,refreshToken也过期了,才让用户重新登录认证。
refreshToken可以用JWT生成,也可以自己生成,不影响认证。
4.建一个Models目录,创建一个映射tokenParameter的类。这个类不是必须,只是为了写着方便。不想这样写,也可以直接读配置,再转成数据。
using System;
namespace demo.Models
{
public class tokenParameter
{
public string Secret { get; set; }
public string Issuer { get; set; }
public int AccessExpiration { get; set; }
public int RefreshExpiration { get; set; }
}
}
5.在前边建好的API - RequestToken中,完成Token和refreshToken的生成和返回。
using Microsoft.AspNetCore.Mvc;
using demo.DTOModels;
using Microsoft.Extensions.Configuration;
using System;
using System.Text;
using demo.Models;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
namespace demo.Controllers
{
public class AuthenticationController : ControllerBase
{
private tokenParameter _tokenParameter = new tokenParameter();
public AuthenticationController()
{
var config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
_tokenParameter = config.GetSection("tokenParameter").Get<tokenParameter>();
}
[HttpPost, Route("requestToken")]
public ActionResult RequestToken([FromBody] LoginRequestDTO request)
{
//这儿在做用户的帐号密码校验。我这儿略过了。
if (request.username == null && request.password == null)
return BadRequest("Invalid Request");
//生成Token和RefreshToken
var token = GenUserToken(request.username, "testUser");
var refreshToken = "123456";
return Ok(new[] { token, refreshToken });
}
//这儿是真正的生成Token代码
private string GenUserToken(string username, string role)
{
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, role),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenParameter.Secret));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var jwtToken = new JwtSecurityToken(_tokenParameter.Issuer, null, claims, expires: DateTime.UtcNow.AddMinutes(_tokenParameter.AccessExpiration), signingCredentials: credentials);
var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
return token;
}
}
}
这个类里,验证帐号密码的代码我略过了。还有,refreshToken给了一个固定串。真实项目这儿就按需要做就好。
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。