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应用程序进行调试.在 ...
随机推荐
- iOS开发:Toast for iPhone
iOS开发:Toast for iPhone 分享一个我写的类似于android的toast的提示框 主要特点: 1,支持屏幕Y轴任意位置显示,设置距离顶/底端距离 2,支持多行文本 3,支持设置 ...
- Active Directory虚拟机搭建域控服务器环境
前言 还是和上一章一样,痛苦过后还是记录下给后来人提供便利为妙. 虚拟机选择:建议Hyper-V或者VMware 系统选择:建议WIindows Server 2003及以上 我这里是使用VMware ...
- 2015最新iherb海淘攻略-图文入门教程-6月免邮
注:仅仅有首次下单才享有新人优惠10$,大家下单之后千万不要取消后.否则之后则不享有新人优惠. 注:眼下Sino-海淘客国际物流已取消,仅有UCS合众速递. IHerb是美国最热门的海淘海购网站之中的 ...
- XShell连接不了虚拟机
本机安装好虚拟机和centeros; 使用xshell连接: linux Could not connect to '127.0.0.1' (port 22): Connection failed. ...
- 九度OJ 1128:求平均年龄 (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2080 解决:1084 题目描述: 班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄,保留到小数点后两位. 输入: 第 ...
- the ACID properties of HBase
http://hbase.apache.org/acid-semantics.html Apache HBase (TM) is not an ACID compliant database. How ...
- Struts2页面遍历
<s:iterator />可以遍历 数据栈里面的任何数组,集合等等 在使用这个标签的时候有三个属性值得我们关注 1. value属性:可选的属性,value属性是指一个被迭代的 ...
- vue-面试
1.单页面应用与多页面应用的去别 2.简述一下Sass.Less,且说明区别? 他们是动态的样式语言,是CSS预处理器,CSS上的一种抽象层.他们是一种特殊的语法/语言而编译成CSS.变量符不一样,l ...
- HDU5171 GTY's birthday gift —— 矩阵快速幂
题目链接:https://vjudge.net/problem/HDU-5171 GTY's birthday gift Time Limit: 2000/1000 MS (Java/Others) ...
- Kattis - whatdoesthefoxsay —— 字符串
题目: Kattis - whatdoesthefoxsay Determined to discover the ancient mystery—the sound that the fox ...