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应用程序进行调试.在 ...
随机推荐
- 改动UITextfield的Placeholder字体的颜色
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...
- ReboletricSample工程搭建
受到 Just Say No to More End-to-End Tests 文章链接:http://googletesting.blogspot.tw/2015/04/just-say-no-t ...
- commons.cli.jar 作用
对命令行进行处理的jar包.处理的步骤主要包括定义.分析和询问.(There are three stages to command line processing. They are the def ...
- RESTful设计模式状态码code说明
一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. 下面是标准RESTfu ...
- 安装 jdk-8u121( jdk1.8 ) Eclipse jee neon java EE 4.6 并配置 中国科学技术大学 http://mirrors.ustc.edu.cn/eclipse/ 仓库源
官网太慢用百度网盘,打不开刷新几次试试 http://pan.baidu.com/s/1qYTUrGK#list/path=%2F 首先下载安装 jdk-8u121-windows-x64.exe ...
- 微信分享配置(js-sdk)
现在的微信分享给朋友-分享到朋友圈 链接带有自定义的title.描述.图片,需要配置js-sdk(地址:mp.weixin.qq.com)微信文档 需要后台配置config的参数,返回给前台 1)de ...
- splittability A SequenceFile can be split by Hadoop and distributed across map jobs whereas a GZIP file cannot be.
splittability CompressedStorage Skip to end of metadata Created by Confluence Administrator, l ...
- Android笔记之文本随滑块移动的SeekBar
效果图 FloatingTextSeekBar.java package com.bu_ish.blog; import android.content.Context; import android ...
- Express中的Ejs模板传值问题
在Ejs模板传值过程中,route下的变量值通过res.sender()中的变量参数传给views, 这时在views中若该变量在javascript代码中使用,可直接使用该变量,不必使用<% ...
- U盘安装Ubuntu 14.04 LTS正式版 出现如下的提示,不能继续,如何操作?
I had a problem (minor annoyance) when booting up Arch linux with a USB drive connected. The problem ...