ASP.NET Core Web API + Angular 仿B站(三)后台配置 JWT 的基于 token 的验证
前言:
本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿。
本系列文章主要参考资料:
微软文档: https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windows
Angular 文档: https://angular.cn/tutorial
Typescript 文档: https://www.typescriptlang.org/docs/home.html
本章额外参考文档:
https://www.dotnettricks.com/learn/angular/token-based-authentication-json-web-token-aspnet-core
https://tools.ietf.org/html/rfc7519
此系列皆使用 C#+Typescript+Angular+EF Core 作为开发环境,使用 VSCode 对 Angular 进行开发同时作为命令行启动器,使用 VS2017 对 ASP.NET Core 进行开发。如果有什么问题或者意见欢迎在留言区进行留言。
如果图片看不清的话请在新窗口打开图片或保存本地查看。
项目 github 地址:https://github.com/NanaseRuri/FakeBilibili
本章内容:建立 ASP.NET Core Web API + Angular 验证
一、配置 ASP.NET Core
首先在 appsetting.json 中添加字段:
"Jwt": {
"Key": "TempPrivateSecretKey",
"Issuer": "localhost:5001"
},

然后在 ConfigureServices 方法中为服务器添加 Jwt 服务:
确定服务的行为:ValidateIssuer = true 验证生成 JWT 的服务器信息;ValidateAudience = true 验证接收 JWT 的服务器;ValidateLifetime = true 检查 JWT 的过期时间;ValidateIssuerSigningKey = true 检查 JWT 的签名。
配置服务的参数: ValidIssuer 待验证的 Jwt 的生成方, ValidAudience 待验证的接收方。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
});
二、创建提供标识的控制器和方法
准备工作:
在此仅提供 ID + 密码 的验证方式,因而新建一个视图模型:
public class LoginModel
{
public string Account { get; set; }
public string Password { get; set; }
public LoginType LoginType { get; set; }
}
创建一个用来加密密码的接口 IEncrypt ,该接口为之前 Encryptor 类方法的提取,然后在 Encryptor 中继承该接口:
public interface IEncrypt
{
string Encrypt(string password,string salt);
}
在 Configure 方法中对该接口进行注册,确保整个应用程序生存期内使用的为同一实例:
services.AddScoped<IEncrypt, Encryptor>();
然后创建一个 API 控制器,在构造函数中对各项参数进行注入:
[Route("api/[controller]")]
[ApiController]
public class AccountController : ControllerBase
{
private IConfiguration _config;
private UserIdentityDbContext _identityDbContext;
private IEncrypt _encryptor;
public AccountController(IConfiguration config, IEncrypt encryptor, UserIdentityDbContext identityDbContext)
{
_config = config;
_identityDbContext = identityDbContext;
_encryptor = encryptor;
}
}
逻辑编写:
对用户进行验证,如果验证通过则生成 Jwt:
[HttpPost]
[Route("Login")]
public async Task<IActionResult> Login(LoginModel account)
{
var user = await ValidateUser(account);
if (user != null)
{
var tokenString = GenerateJsonWebToken(user);
return Ok(new { token = tokenString });
}
return Unauthorized();
}
验证方法:
判断用户是否存在 => 获取盐值 => 进行加密后验证密码是否正确:
async Task<UserIdentity> ValidateUser(LoginModel account)
{
UserIdentity user = await GetUser(account);
if (user == null)
{
return null;
}
var hashPassword = _encryptor.Encrypt(account.Password, user.Salt);
if (user.Password == hashPassword)
{
return user;
}
return null;
}
通过正则表达式判断输入的登录方式的类型以通过不同字段获取用户:
async Task<UserIdentity> GetUser(LoginModel account)
{
string regexId = @"^\d+$";
string regexUserName = @"^\w+[\d\w]*$";
string regexEmail = @"[a-zA-Z\d]+@[a-zA-Z\d]+.";
UserIdentity user = new UserIdentity();
if (Regex.IsMatch(account.Account,regexId))
{
user = await _identityDbContext.Users.FirstOrDefaultAsync(u => u.Id == Int32.Parse(account.Account));
}
else if (Regex.IsMatch(account.Account,regexUserName))
{
user = await _identityDbContext.Users.FirstOrDefaultAsync(u => u.UserName == account.Account);
}
else if (Regex.IsMatch(account.Account,regexEmail))
{
user = await _identityDbContext.Users.FirstOrDefaultAsync(u => u.Email == account.Account);
}
return user;
}
生成 Jwt 的方法:
由于使用的是 Sha256 签名算法,此处 SymmetricSecurityKey 要求 _config["Jwt:Key"] 不少于 16 位,否则在最后一步中会抛出异常。
string GenerateJsonWebToken(UserIdentity user)
{
//定义密钥
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
//定义要使用的密钥和进行哈希计算的算法
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//定义待添加 Jwt 的 payload 字段
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
//定义 Jwt 的 payload 字段
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
claims: claims,
expires: DateTime.Now.AddMinutes(),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
运行程序,在 Postman 中对该方法进行测试:


将验证成功时返回的令牌放到 jwt.io 中进行检测:https://jwt.io/#encoded-jwt


ASP.NET Core Web API + Angular 仿B站(三)后台配置 JWT 的基于 token 的验证的更多相关文章
- ASP.NET Core Web API + Angular 仿B站(一) 目的分析以及创建 WebAPI + Angular7 项目
前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...
- ASP.NET Core Web API + Angular 仿B站(二)后台模型创建以及数据库的初始化
前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...
- 在ASP.NET Core Web API中为RESTful服务增加对HAL的支持
HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务 ...
- ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)
GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...
- asp.net core web api 生成 swagger 文档
asp.net core web api 生成 swagger 文档 Intro 在前后端分离的开发模式下,文档就显得比较重要,哪个接口要传哪些参数,如果一两个接口还好,口头上直接沟通好就可以了,如果 ...
- ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程
ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程 翻译自:地址 在今年年初,我整理了有关将JWT身份验证与ASP.NET Core Web API和Angular一起使用的详 ...
- 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)
对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...
- 在ASP.NET Core Web API上使用Swagger提供API文档
我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...
- Docker容器环境下ASP.NET Core Web API应用程序的调试
本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...
随机推荐
- Java Web Start
1. JNLP 2. Security issue: https://java.com/en/download/help/win_controlpanel.xml Windows 7, Vista C ...
- Hibernate中的Sesson操作
一.Session概述 Session是应用程序与数据库之间的一个会话,是Hibernate运作的中心,持久层操作的基础,相当于JDBC中的Connection.Session对象是通过Session ...
- 九度OJ 1110:小白鼠排队 (排序)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1734 解决:1054 题目描述: N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的 ...
- java的取出map里所有元素的两种方式
/* * 取出map元素的两种方式 */package com.map.test; import java.util.HashMap;import java.util.Iterator;import ...
- wprintf、wcout无法输出中文的解决方案
在C语言中,若wprintf无法输出中文,调用函数setlocale(int category, const char *locale)设置locale即可输出中文 此方法也可用于C++中 例: #i ...
- java读取properties文件中参数值
在类文件中加入代码: //config.properties.sysInfo //sysInfo.properties在文件夹的路径为/src/config/properties/sysInfo.pr ...
- SAP 系统账期开关
(1)OB52 财务账期-C 财务维护表 T001B[维护表T001B] (2)OB29 -C FI 财政年变式 (3)MMPV / MMRV -物料账期 MMPV 商品会计期间设置-结帐期间 [ 如 ...
- sap人员编制
[转]中小SAP项目中的人员编制 转自http://w39.itpub.net/post/24/398817 对于SAP项目来说,常有人把项目所需的人员说的很多--每个模块一个内部顾问和一个开发的 ...
- 异步模式模式Future(结合Callable可以获取线程返回结果)
submit 和 excute是有啥区别 如果有这样的需求: 多线程实现下载,提高效率. 不论是Thread类还是Runnable接口重写run方法,有个特点就是没有返回值~~~~~~ 我都主线程 如 ...
- win8.1 保护眼睛的颜色设置
reg add "HKEY_CURRENT_USER\Control Panel\Appearance\New Schemes\Current Settings SaveAll\Sizes\ ...