1、前言

  这块儿当时在IdentityServer4和JWT之间犹豫了一下,后来考虑到现状,出于3个原因,暂时放弃了IdentityServer4选择了JWT:

(1)目前这个前端框架更适配JWT;

(2)前后端分离的项目,如果上IdentityServer4,还要折腾点儿工作,比如前端配置、多余的回调等;

(3)跨度太大,团队、系统、历史数据接入都是问题,解决是可以解决,但时间有限,留待后续吧;

  当然,只是暂时放弃,理想中的最佳实践还是IdentityServer4做统一鉴权的。

2、JWT认证实现

(1)Common项目下定义JWTConfig配置对象

(2)系统配置文件中增加JWT参数配置

此处配置与(1)中的配置对象是对应的。

(3)JWT处理程序及相关服务注册

  1. services.Configure<JWTConfig>(Configuration.GetSection("JWT"));
  2. var jwtConfig = Configuration.GetSection("JWT").Get<JWTConfig>();
  3. services.AddAuthentication(options =>
  4. {
  5. options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  6. options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  7. })
  8. .AddJwtBearer(options =>
  9. {
  10. options.TokenValidationParameters = new TokenValidationParameters
  11. {
  12. ValidateIssuer = true,
  13. ValidIssuer = jwtConfig.Issuer,
  14. ValidateIssuerSigningKey = true,
  15. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SymmetricSecurityKey)),
  16. ValidateAudience = false,
  17. ValidateLifetime = true,
  18. ClockSkew = TimeSpan.FromMinutes()
  19. };
  20. options.Events = new JwtBearerEvents
  21. {
  22. OnTokenValidated = context =>
  23. 23 {
  24. 24 var userContext = context.HttpContext.RequestServices.GetService<UserContext>();
  25. 25 var claims = context.Principal.Claims;
  26. 26 userContext.ID = long.Parse(claims.First(x => x.Type == JwtRegisteredClaimNames.Sub).Value);
  27. 27 userContext.Account = claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value;
  28. 28 userContext.Name = claims.First(x => x.Type == ClaimTypes.Name).Value;
  29. 29 userContext.Email = claims.First(x => x.Type == JwtRegisteredClaimNames.Email).Value;
  30. 30 userContext.RoleId = claims.First(x => x.Type == ClaimTypes.Role).Value;
  31. 31
  32. 32 return Task.CompletedTask;
  33. 33 }
  34. };
  35. });
  36. JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

  上述代码中注意红色那部分Token验证成功的事件注册,其目的是认证成功之后,从JWT中取出必要信息构建当前用户上下文,这个上下文信息非常重要,但凡涉及到需要获取当前用户相关信息的部分,都要依赖它,后续文章中对应部分还会提及。

(4)登录并写入Token

  1. /// <summary>
  2. /// 登录
  3. /// </summary>
  4. /// <param name="userDto"></param>
  5. /// <returns></returns>
  6. [AllowAnonymous]
  7. [HttpPost("login")]
  8. public async Task<IActionResult> Login([FromBody]SysUserDto userDto)
  9. {
  10. var validateResult = await _accountService.ValidateCredentials(userDto.Account, userDto.Password);
  11. if (!validateResult.Item1)
  12. {
  13. return new NotFoundObjectResult("用户名或密码错误");
  14. }
  15.  
  16. var user = validateResult.Item2;
  17. var claims = new Claim[]
  18. {
  19. new Claim(ClaimTypes.NameIdentifier, user.Account),
  20. new Claim(ClaimTypes.Name, user.Name),
  21. new Claim(JwtRegisteredClaimNames.Email, user.Email),
  22. new Claim(JwtRegisteredClaimNames.Sub, user.ID.ToString()),
  23. new Claim(ClaimTypes.Role, user.RoleId)
  24. };
  25.  
  26. var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConfig.SymmetricSecurityKey));
  27.  
  28. var token = new JwtSecurityToken(
  29. issuer: _jwtConfig.Issuer,
  30. audience: null,
  31. claims: claims,
  32. notBefore: DateTime.Now,
  33. expires: DateTime.Now.AddHours(),
  34. signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
  35. );
  36.  
  37. var jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
  38.  
  39. return new JsonResult(new { token = jwtToken });
  40. }

(5)前端Token状态保存

  一般来讲,在后端登录成功返回前端之后,前端需要保存此token以保持状态,否则一刷新全完蛋,那我们来看看前端怎么实现。由于前端项目引入了Vuex来保持状态,那api调用、状态操作自然就放在store中,我们来看看登录对应的store。打开前端源码,找到user这个store:

  我们看到,登录完毕,调用SET_TOKEN这个mutation提交token状态变更保存Token,这个mutation及其背后的state如下如下:

同时,在登录action中,登录成功之后,我们还发现了一行代码:

  此setToken引自前端工具类,auth.js,代码如下:

  1. import Cookies from 'js-cookie'
  2.  
  3. const TokenKey = 'ngcc_mis_token'
  4.  
  5. export function getToken() {
  6. return Cookies.get(TokenKey)
  7. }
  8.  
  9. export function setToken(token) {
  10. return Cookies.set(TokenKey, token)
  11. }
  12.  
  13. export function removeToken() {
  14. return Cookies.remove(TokenKey)
  15. }

  至此我们明白了前端的机制,把token写入Vuex状态的同时,再写入cookie。那这里问一句,只写入Vuex状态,行不行呢?不行,因为浏览器一刷新,所有前端对象就会销毁,包括Vuex对象,这样会导致前端丢失会话。

3、总结

  以上就是系统认证的实现,大家摸清楚各种认证方案、优缺点、特点,多深入源码、机制,遇到问题自然会手到擒来。

SET_TOKEN

Core + Vue 后台管理基础框架2——认证的更多相关文章

  1. Core + Vue 后台管理基础框架0——开篇

    1.背景 最近,打算新开个项目,鉴于团队技术栈,选型.net core + vue,前后端分离.本打算捡现成的轮子的,github上大致逛了逛,总发现这样那样的不太适合心中那些“完美实践”,例如:Ab ...

  2. Core + Vue 后台管理基础框架3——后端授权

    1.前言 但凡业务系统,授权是绕不开的一环.见过太多只在前端做菜单及按钮显隐控制,但后端裸奔的,觉着前端看不到,系统就安全,掩耳盗铃也好,自欺欺人也罢,这里不做评论.在.NET CORE中,也见过不少 ...

  3. Core + Vue 后台管理基础框架4——前端授权

    1.前言 上篇,我们讲了后端的授权.与后端不同,前端主要是通过功能入口如菜单.按钮的显隐来控制授权的.具体来讲,就是根据指定用户的制定权限来加载对应侧边栏菜单和页面内的功能按钮.我们一个个来讲. 2. ...

  4. Core + Vue 后台管理基础框架9——统一日志

    1.背景 前阵子有园友留言,提到日志相关的东西,同时,最近圈子里也有提到日志这个东西.一个充分.集中的统一日志平台还是很有必要的,否则系统出问题了只能靠猜或者干瞪眼.何谓充分,日志记录满足最低要求.出 ...

  5. Core + Vue 后台管理基础框架7——APM

    1.前言 APM,又称应用性能统计,主要用来跟踪请求调用链,每个环节调用耗时,为我们诊断系统性能.定位系统问题提供了极大便利.本系统采用的是Elastic Stack体系中的APM,主要是之前部门搞P ...

  6. Core + Vue 后台管理基础框架8——Swagger文档

    1.前言 作为前后端分离的项目,或者说但凡涉及到对外服务的后端,一个自描述,跟代码实时同步的文档是极其重要的.说到这儿,想起了几年前在XX速运,每天写完代码,还要给APP团队更新文档的惨痛经历.给人家 ...

  7. Core + Vue 后台管理基础框架1——运行系统

    1.down源码 git clone https://github.com/KINGGUOKUN/SystemManagement.git,项目目录如下: 2.还原数据库 找到项目根目录下System ...

  8. hsweb 企业后台管理基础框架

    hsweb 详细介绍 业务功能 现在: 权限管理: 权限资源-角色-用户. 配置管理: kv结构,自定义配置.可通过此功能配置数据字典. 脚本管理: 动态脚本,支持javascript,groovy, ...

  9. 如何在ASP.NET Core中实现一个基础的身份认证

    注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...

随机推荐

  1. 学习python-20191230(1)-Python Flask高级编程开发鱼书_第04章_应用、蓝图与视图函数

    视频06: 1.自动导包快捷键——默认为alt + enter 键组合          选中的字符由小写变为大写——Ctrl + Shift + U键组合 2.DataRequired()——防止用 ...

  2. Centos7下常见命令

    1:  hostnamectl set-hostname  oldgirl   设置主机名直接生效 2:  hostname oldboy   (暂时生效,重启后恢复原来主机名)

  3. Hadoop伪分布式HDFS环境搭建和使用

    1.环境要求 Java版本不低于Hadoop要求,并配置环境变量 2.安装 1)在网站hadoop.apache.org下载稳定版本的Hadoop包 2)解压压缩包 检查Hadoop是否可用 hado ...

  4. navisworks安装未完成,某些产品无法安装的解决方法

    navisworks提示安装未完成,某些产品无法安装该怎样解决呢?,一些朋友在win7或者win10系统下安装navisworks失败提示navisworks安装未完成,某些产品无法安装,也有时候想重 ...

  5. Linux(CentOS_7.6)安装Nginx

    1.安装依赖 12 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.下载Nginx并解压 1234567 c ...

  6. JS计算日期加天数后的日期(起始日期+有效天数=截至日期)

    /** * 优惠券有效期 * startDate:起始日期 * valueTime:有效天数 */ function transferCouponValueTime(startDate,valueTi ...

  7. 吴裕雄--天生自然KITTEN编程:青蛙答题过河

  8. python 常用模块介绍

    1.定义 模块:用来从逻辑上组织python代码(变量.函数.类,逻辑),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test). 包:用来从逻辑上组织模块的,本质就是 ...

  9. 监控Linux系统所选的服务所占进程内存占用

    [代码] #!/bin/bash #程序功能描述: # 监控系统所选的服务所占进程内存占用 #作者:孤舟点点 #版本:1.0 #创建时间:-- :: PATH=/bin:/sbin:/usr/bin: ...

  10. JavaScript是如何工作的(一)

    简评:JavaScript 是越来越受欢迎了,很多团队都在采用这些语言工作.前端.后端.嵌入式设备等等,都可以看见它的身影.虽然我们知其然,但又知其所以然吗? 大家应该都知道 JavaScript 是 ...