前言:

本系列文章主要为对所学 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. CentOS安装配置

    1.准备安装 1.1 系统简介 CentOS 是什么? CentOS是一个基于Red Hat 企业级 Linux 提供的可自由使用的源代码企业级的 Linux 发行版本.每个版本的 CentOS 都会 ...

  2. Erlang二进制模式匹配

    Erlang的模式匹配用来处理二进制数据可谓是得心应手.不仅直观,而且超乎想象的简单.在C++中,处理二进制数据首先要管理缓冲区.然后再按字节进行操作,如果要处理的数据不是按字节对齐,则需要进行位移等 ...

  3. EasyPlayer iOS开源流媒体播放器中AAC解码PCM问题

    本文转自EasyDarwin开源团队成员Penggy的博客:http://www.jianshu.com/p/feeb107b6657 最近遇到在 iOS 平台上实时播放 AAC 音频数据流, 一开始 ...

  4. EasyDarwin开源流媒体服务器将select改为epoll的方法

    本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听所有网络读写事件,Even ...

  5. error LNK1112: module machine type 'X86' conflicts with target machine type 'x64'

    1 这个error是什么原因造成的 cmake默认选择的是x86,即32位的生成子. 2 怎么解决这个error 在cmake ..的时候,在后面加上“-G "Visual Studio 1 ...

  6. 淘宝客网站SEO及赚钱与揭密

  7. 阿里妈妈-RAP项目的实践(1)

    在同事的推荐下,去了解了一下http://thx.github.io/RAP/study.html#,它是发现在前后端分离开发的神器 下面我们来简单上一组代码,来简单了解一下rap <!DOCT ...

  8. git推送已有项目到gitee

    有时候会接收一个项目,这个项目已有git版本控制,但git 远端服务器地址已失效(员工离职,原先是推送到他个人gitee上的). 要按照如下步骤,将该项目推送到gitee. 1.先去gitee上新建一 ...

  9. MATLAB 2013b .m 文件关联

    使用绿色版的MATLAB无法自动关联.m文件,在网上查到的解决办法是,在MATLAB里运行如下命令: cwd=pwd; cd([matlabroot '\toolbox\matlab\winfun\p ...

  10. [haoi2014]穿越封锁线

    这题需要注意的一点是射线法需要考虑边界,而且题目对边界的限制极为严格. dcmp(v[i%n].x-x)<=0&&dcmp(v[(i+1)%n].x-x)>0 dcmp(v ...