前言:

本系列文章主要为对所学 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 json按key值排序

    最近有个需求需要把json按key值进行排序,可是js并没有直接的函数可以对json进行排序的这么办呢? 然后想到了一个间接的方法来实现: 1.将json中的key值取出,存在一个数组中,然后对这个数 ...

  2. 制作一个塔防游戏 Cocos2d-x 2.1.4 (一)

    在这篇文章,将会学习到怎样制作一个塔防游戏.在这其中,学习怎样在设定的时间内出现一波波的敌人,使这些敌人沿着指定的路点前进.怎样在地图上指定的位置创建炮塔.怎样使炮塔射击敌人,怎样可视化调试路点和炮塔 ...

  3. HTML5学习笔记简明版(9):变化的元素和属性

    改变的元素(Element) 下面元素在HTML5里的使用方法稍作改动以便能在web里更好的使用或者起到更大作用: 没有href属性的a元素将显示成一个占位符,并且a元素内部如今支持flow cont ...

  4. 【BZOJ3197】[Sdoi2013]assassin 树同构+动态规划+KM

    [BZOJ3197][Sdoi2013]assassin Description Input Output Sample Input 4 1 2 2 3 3 4 0 0 1 1 1 0 0 0 Sam ...

  5. wcf服务发布时,目录中没有文件生成

    1.删除原有的配置文件

  6. File syncing and sharing software with file encryption and group sharing, emphasis on reliability and high performance.

    http://seafile.com/ showdoc haiwen/seafile: File syncing and sharing software with file encryption a ...

  7. [Java SE] 字符串连接

    Java 支持多种字符串连接方式,总结如下: package cn.spads.tool.string; import java.text.MessageFormat; /** * <b> ...

  8. ABAP 取字段的简短描述

    取字段的简短描述: 取字段描述 DATA inttab LIKE STANDARD TABLE OF dfies WITH HEADER LINE. CALL FUNCTION 'DDIF_FIELD ...

  9. Chain of Responsibility Pattern

    1.Chain of Responsibility模式:将可能处理一个请求的对象链接成一个链,并将请求在这个链上传递,直到有对象处理该请求(可能需要提供一个默认处理所有请求的类,例如MFC中的Cwin ...

  10. 有关Option.inSamplSize 和 Compress 图片压缩

    1.图片占用内存:占用的内存 = 图片长度 * 图片宽度 * 单位像素占用的字节数 注: 图片长度和图片宽度就是图片在行列上的像素数量. 图片格式: ALPHA_8:表示8位Alpha位图,即A=8, ...