Dotnet core使用JWT认证授权最佳实践(一)
最近,团队的小伙伴们在做项目时,需要用到JWT认证。遂根据自己的经验,整理成了这篇文章,用来帮助理清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.201Commit: b1768b4ae7Runtime Environment:OS Name: Mac OS XOS Version: 10.15OS Platform: DarwinRID: osx.10.15-x64Base Path: /usr/local/share/dotnet/sdk/3.1.201/Host (useful for support):Version: 3.1.3Commit: 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]
首先,在这个环境下建立工程:
创建Solution
% dotnet new sln -o demo
The template "Solution File" was created successfully.
用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.
把Demo项目加到Solution中
% dotnet sln add demo/demo.csproj
Project `demo/demo.csproj` added to the solution.
安装Swagger(这步非必须,我习惯用Swagger,不习惯用Postman)
% dotnet add package Swashbuckle.AspNetCore
log : Restore completed in 2.75 sec for demo/demo.csproj.
安装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
在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是认证的第一步。
用户进到系统,在验证用户帐号密码后,需要根据用户的数据,把Token返回给用户。
这个过程其实跟认证没什么关系,只是一个普通的API功能。
工程下加一个目录DTOModels,创建一个LoginRequestDTO的类,用于定义API的输入参数。
using System;namespace demo.DTOModels
{public class LoginRequestDTO{public string username { get; set; }public string password { get; set; }}
}
创建一个控制器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();}}
}
生成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生成,也可以自己生成,不影响认证。
建一个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; }}
}
在前边建好的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和RefreshTokenvar 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给了一个固定串。真实项目这儿就按需要做就好。
(未完待续)
动动手指,点个在看
您的赞赏是我最大的鼓励
I will be more solid with your donations
Dotnet core使用JWT认证授权最佳实践(一)相关推荐
- Dotnet core使用JWT认证授权最佳实践(二)
最近,团队的小伙伴们在做项目时,需要用到JWT认证.遂根据自己的经验,整理成了这篇文章,用来帮助理清JWT认证的原理和代码编写操作. 第一部分:Dotnet core使用JWT认证授权最佳实践(一) ...
- LDAP身份认证管理最佳实践
LDAP身份认证管理最佳实践 轻型级目录访问协议(LDAP)为数据库访问控制提供了一个开源的,跨平台的解决方案.它是企业级的通用身份和访问管理(IAM)工具,但如果不遵循适当的管理协议,则可能会带来严 ...
- Asp.Net Core基于JWT认证的数据接口网关Demo
Asp.Net Core基于JWT认证的数据接口网关Demo 近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求 ...
- .net core 学习小结之 JWT 认证授权
新增配置文件 {"Logging": {"IncludeScopes": false,"Debug": {"LogLevel&qu ...
- .NET Core 集成JWT认证
JWT(Json web token)就不用过多的介绍了,在 .NET Core 开发中使用JWT进行认证也是比较常见的,而且接入过程也比较简单,随便配置配置就好了. 要想使用JWT,仅仅只需要在项目 ...
- ASP.NET Core Web API 最佳实践指南
原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 介绍 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难 ...
- 基于.NetCore3.1搭建项目系列 —— 认证授权方案之Swagger加锁
1 开始 在之前的使用Swagger做Api文档中,我们已经使用Swagger进行开发接口文档,以及更加方便的使用.这一转换,让更多的接口可以以通俗易懂的方式展现给开发人员.而在后续的内容中,为了对a ...
- 你不知道的 React 最佳实践
React ⚛️ React 是一个用于开发用户界面的 JavaScript 库, 是由 Facebook 在 2013 年创建的. React 集成了许多令人兴奋的组件.库和框架[1]. 当然,开发 ...
- 三分钟学会.NET Core Jwt 策略授权认证
一.前言 大家好我又回来了,前几天讲过一个关于Jwt的身份验证最简单的案例,但是功能还是不够强大,不适用于真正的项目,是的,在真正面对复杂而又苛刻的客户中,我们会不知所措,就现在需要将认证授权这一块也 ...
最新文章
- javascript中replace使用方法总结
- C语言中,#include 和#include 的区别和注意点
- UDP广播之socket bad address 错误被解决,舒服
- 5分钟安全顾问 - 针对家庭办公室用户的简单防火墙安装
- linuxpython重定向_linux命令重定向、、 1、 2、 1、 2、
- Spring Boot中使用Swagger CodeGen生成REST client
- bat判断3306端口号是否被占用
- html的meta属性
- Java反射机制是什么?
- Java嵌入式数据库H2学习总结(二)——在Web应用程序中使用H2数据库
- 14英寸电脑长宽多少_华为MateBook 14 2020款 14英寸轻薄笔记本王者升级
- 实用 —— PowerCLI (二)
- Atitit object 和class的理解 目录 1.1. 发现很多Object的方法都是相同的,他们被重复地放在一个个对象当中,太浪费了。	1 1.2. 那我们怎么把这些Object给创建起来
- Android Studio - 安装插件GsonFormat
- 酷狗音乐的临时缓存文件转换为MP3文件,java源码
- Python 中拼音库 PyPinyin 的使用
- 数字特征值-对数字求特征值是常用的编码算法,奇偶特征是一种简单的特征值
- redis sorted_set跳跃表(skiplist)
- 发现了一个可以让网盘加速的小工具(文末还有一个用了很久的小方法)
- 两件事:李一男、CS游戏