前言:

本系列文章主要为对所学 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. 后端程序员看前端想死(三)是不是该学点js了

    CSS盒子模型 div布局 js 这些都懂一点,但仅仅是懂一点,有时间就学一下咯

  2. vuex 介绍

    vuex是为vue.js开发的状态管理模式,负责vue的状态管理,状态管理是干啥的呢,举个栗子,比如一个酒店,哪间屋子入住了客人,哪间屋子客人退房了,客人退房后,房间有没有清扫过,这些都需要去记录,以 ...

  3. pygame 安装教程

    步骤: 1.去官网下载PyGame 注意:要下载对应版本的包 官网地址:http://www.pygame.org/download.shtml 其中,如果python为以下版本: python 3. ...

  4. ESXi 5.5 RTL9168E网卡驱动 找到网卡

    如果你对专业服务器的价格望而却步,恰巧又想在普通的PC上安装ESXi,恰巧又是ESXi 5.5版本,那么这篇文章中提及的问题你可能会遇到,并能给你提供一些帮助. 1.成功安装重启以后提示“no boo ...

  5. [Phoenix] 六、MR在Ali-Phoenix上的使用

    摘要: 在云HBASE上利用MR BULKLOAD入库PHOENIX表或通过MR构建PHOENIX索引表. 一.MR在Phoenix上的用途 利用MR对Phoenix表(可带有二级索引表)进行Bulk ...

  6. go网关

    package main import ( "flag" "fmt" "io" "net" "os" ...

  7. MARA 附加结构(增强字段)

  8. duilib查看过的资料整理

    1.duilib中各个类的简单介绍 2.源码分析 3.各个控件可以设置的属性 4.duilib的消息流程处理 5.工程编译入门 6.MFC中混合使用duilib制作界面 7.从Win32窗口到duil ...

  9. Shell之内容匹配与格式输出

    对于大文本或者有些特定格式的文本,有时我们要查找特定内容或定位指定的区域,这样就需要内容匹配. 关于内容匹配,我们常使用的有几个命令: grep,支持正则,查找包含有匹配项的行. cut,提取指定的列 ...

  10. windows 下python搭建环境

    一.python安装 1,首先访问https://www.python.org/downloads/windows/去下载python版本. 2. 选择3.5版本,installer文件类型(因为3. ...