前言:

本系列文章主要为对所学 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 的验证的更多相关文章

  1. ASP.NET Core Web API + Angular 仿B站(一) 目的分析以及创建 WebAPI + Angular7 项目

    前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...

  2. ASP.NET Core Web API + Angular 仿B站(二)后台模型创建以及数据库的初始化

    前言: 本系列文章主要为对所学 Angular 框架的一次微小的实践,对 b站页面作简单的模仿. 本系列文章主要参考资料: 微软文档: https://docs.microsoft.com/zh-cn ...

  3. 在ASP.NET Core Web API中为RESTful服务增加对HAL的支持

    HAL(Hypertext Application Language,超文本应用语言)是一种RESTful API的数据格式风格,为RESTful API的设计提供了接口规范,同时也降低了客户端与服务 ...

  4. ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)

    GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...

  5. asp.net core web api 生成 swagger 文档

    asp.net core web api 生成 swagger 文档 Intro 在前后端分离的开发模式下,文档就显得比较重要,哪个接口要传哪些参数,如果一两个接口还好,口头上直接沟通好就可以了,如果 ...

  6. ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程

    ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程 翻译自:地址 在今年年初,我整理了有关将JWT身份验证与ASP.NET Core Web API和Angular一起使用的详 ...

  7. 使用 Swagger 自动生成 ASP.NET Core Web API 的文档、在线帮助测试文档(ASP.NET Core Web API 自动生成文档)

    对于开发人员来说,构建一个消费应用程序时去了解各种各样的 API 是一个巨大的挑战.在你的 Web API 项目中使用 Swagger 的 .NET Core 封装 Swashbuckle 可以帮助你 ...

  8. 在ASP.NET Core Web API上使用Swagger提供API文档

    我在开发自己的博客系统(http://daxnet.me)时,给自己的RESTful服务增加了基于Swagger的API文档功能.当设置IISExpress的默认启动路由到Swagger的API文档页 ...

  9. Docker容器环境下ASP.NET Core Web API应用程序的调试

    本文主要介绍通过Visual Studio 2015 Tools for Docker – Preview插件,在Docker容器环境下,对ASP.NET Core Web API应用程序进行调试.在 ...

随机推荐

  1. Memcache介绍

    面临的问题 对于高并发高訪问的 Web应用程序来说.数据库存取瓶颈一直是个令人头疼的问题. 特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰值已经达到500的时候,那你的程序执行离崩溃的 ...

  2. 《UNIX 环境高级编程》编译环境的搭建( 运行本专栏代码必读 )

    第一步:搭建基本的编译环境 安装gcc, g++, bulid-essential等编译软件 第二步:下载本书示例源码包 可在这里下载 www.apuenook.com 第三步:解压下载到的包并放在用 ...

  3. 优化梯度计算的改进的HS光流算法

    前言 在经典HS光流算法中,图像中两点间的灰度变化被假定为线性的,但实际上灰度变化是非线性的.本文详细分析了灰度估计不准确造成的偏差并提出了一种改进HS光流算法,这种算法可以得到较好的计算结果,并能明 ...

  4. EasyDarwin EasyClient开源流媒体播放器,支持多窗口显示

    EasyDarwin开源团队开源的EasyClient客户端将支持流媒体采集.编码.推送.播放.抓图.录像.Onvif 等全套功能(大家持续关注我们Github的commit),其中播放功能是开源流媒 ...

  5. Vue入门(一) 环境配置

    Node.js 安装,https://nodejs.org/en/  默认安装就可以 安装好后测试版本,cmd  键入命令 1.node -v 2.npm -v 安装,淘宝 NPM         n ...

  6. 在yum出问题的情况下安装某个rpm包的方法

    1 核心命令 rpm -i 2 方法 centos镜像站去找到所有的rpm包. 安装这个rpm包,发现有一个依赖没有安装,就去下载安装.因为整体的包是有限的,因此终会收敛的. 比如安装rpmbuild ...

  7. Create a /etc/yum.repos.d/mongodb-org-4.0.repo

    Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux — MongoDB Manual https://doc ...

  8. BZOJ 2069 POI2004 ZAW 堆优化Dijkstra

    题目大意:给定一张无向图.每条边从两个方向走各有一个权值,求从点1往出走至少一步之后回到点1且不经过一条边多次的最短路 显然我们须要从点1出发走到某个和点1相邻的点上,然后沿最短路走到还有一个和点1相 ...

  9. ABAP读取工单状态 STATUS_READ

    *&---------------------------------------------------------------------* *& Report YDEMO_013 ...

  10. iOS中版本号的获取及其意义

    //对应的是发布的版本号,也就是build #define APP_VERSION [[[NSBundle mainBundle] infoDictionary] objectForKey:@&quo ...