前言:

本系列文章主要为对所学 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. 不使用flash实现复制文字(图片)到剪贴板

    <div>这里是待复制的文字或图片</div> var range = document.createRange(); var referenceNode = document ...

  2. CentOS 7.2 , YUM 方式安装VSC

    1.引入VSC站点key和repo地址 sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh -c ' ...

  3. hdu1878欧拉回路(DFS+欧拉回路)

    欧拉回路 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  4. hive编程入门课程(加精)

    hive编程入门课程 http://wenku.baidu.com/link?url=BfyZWjz48G_6UJImzWw39OLB0sUrIYEYxoxNpaFbADUQekmOvQy4FPY1f ...

  5. 1492: [NOI2007]货币兑换Cash【CDQ分治】

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 4166  Solved: 1736[Submit][Sta ...

  6. 统计 与 数学 induction 归纳 deduction 演绎 吴喜之老师

    “统计的思维方式是归纳(induction),也就是从数据所反映的现实得到比较一般的模型,希望以此解释数据所代表的那部分世界.这和以演绎(deduction)问哦主的数学思维方式相反,演绎是在一些人为 ...

  7. 超实用的 Nginx 极简教程,覆盖了常用场景(转)

    概述 安装与使用 安装 使用 nginx 配置实战 http 反向代理配置 负载均衡配置 网站有多个 webapp 的配置 https 反向代理配置 静态站点配置 搭建文件服务器 跨域解决方案 参考 ...

  8. leeetcode 735. Asteroid Collision

    We are given an array asteroids of integers representing asteroids in a row. For each asteroid, the ...

  9. tableView滑动时cell消失

    最近做的工程中,出现个奇怪的问题吗,就是上下滑动tableView的时候,cell还未出屏幕就消失了,找了很久找到了原因,是因为界面中需要的cell有很多种,而有的cell的高度是一开始算出来或是固定 ...

  10. .Net-Mongodb学习大全网址

    http://www.yuanjiaocheng.net/csharpmongo/16.html 介绍 在上一篇文章中,我们继续探索MongoDb .NET驱动程序中的数据序列化. 我们查看了各种属性 ...