Core + Vue 后台管理基础框架2——认证
1、前言
这块儿当时在IdentityServer4和JWT之间犹豫了一下,后来考虑到现状,出于3个原因,暂时放弃了IdentityServer4选择了JWT:
(1)目前这个前端框架更适配JWT;
(2)前后端分离的项目,如果上IdentityServer4,还要折腾点儿工作,比如前端配置、多余的回调等;
(3)跨度太大,团队、系统、历史数据接入都是问题,解决是可以解决,但时间有限,留待后续吧;
当然,只是暂时放弃,理想中的最佳实践还是IdentityServer4做统一鉴权的。
2、JWT认证实现
(1)Common项目下定义JWTConfig配置对象

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

此处配置与(1)中的配置对象是对应的。
(3)JWT处理程序及相关服务注册
services.Configure<JWTConfig>(Configuration.GetSection("JWT"));
var jwtConfig = Configuration.GetSection("JWT").Get<JWTConfig>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtConfig.Issuer,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SymmetricSecurityKey)),
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes()
};
options.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
23 {
24 var userContext = context.HttpContext.RequestServices.GetService<UserContext>();
25 var claims = context.Principal.Claims;
26 userContext.ID = long.Parse(claims.First(x => x.Type == JwtRegisteredClaimNames.Sub).Value);
27 userContext.Account = claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value;
28 userContext.Name = claims.First(x => x.Type == ClaimTypes.Name).Value;
29 userContext.Email = claims.First(x => x.Type == JwtRegisteredClaimNames.Email).Value;
30 userContext.RoleId = claims.First(x => x.Type == ClaimTypes.Role).Value;
31
32 return Task.CompletedTask;
33 }
};
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
上述代码中注意红色那部分Token验证成功的事件注册,其目的是认证成功之后,从JWT中取出必要信息构建当前用户上下文,这个上下文信息非常重要,但凡涉及到需要获取当前用户相关信息的部分,都要依赖它,后续文章中对应部分还会提及。
(4)登录并写入Token
/// <summary>
/// 登录
/// </summary>
/// <param name="userDto"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody]SysUserDto userDto)
{
var validateResult = await _accountService.ValidateCredentials(userDto.Account, userDto.Password);
if (!validateResult.Item1)
{
return new NotFoundObjectResult("用户名或密码错误");
} var user = validateResult.Item2;
var claims = new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.Account),
new Claim(ClaimTypes.Name, user.Name),
new Claim(JwtRegisteredClaimNames.Email, user.Email),
new Claim(JwtRegisteredClaimNames.Sub, user.ID.ToString()),
new Claim(ClaimTypes.Role, user.RoleId)
}; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConfig.SymmetricSecurityKey)); var token = new JwtSecurityToken(
issuer: _jwtConfig.Issuer,
audience: null,
claims: claims,
notBefore: DateTime.Now,
expires: DateTime.Now.AddHours(),
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
); var jwtToken = new JwtSecurityTokenHandler().WriteToken(token); return new JsonResult(new { token = jwtToken });
}
(5)前端Token状态保存
一般来讲,在后端登录成功返回前端之后,前端需要保存此token以保持状态,否则一刷新全完蛋,那我们来看看前端怎么实现。由于前端项目引入了Vuex来保持状态,那api调用、状态操作自然就放在store中,我们来看看登录对应的store。打开前端源码,找到user这个store:

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

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

此setToken引自前端工具类,auth.js,代码如下:
import Cookies from 'js-cookie'
const TokenKey = 'ngcc_mis_token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
至此我们明白了前端的机制,把token写入Vuex状态的同时,再写入cookie。那这里问一句,只写入Vuex状态,行不行呢?不行,因为浏览器一刷新,所有前端对象就会销毁,包括Vuex对象,这样会导致前端丢失会话。
3、总结
以上就是系统认证的实现,大家摸清楚各种认证方案、优缺点、特点,多深入源码、机制,遇到问题自然会手到擒来。
Core + Vue 后台管理基础框架2——认证的更多相关文章
- Core + Vue 后台管理基础框架0——开篇
1.背景 最近,打算新开个项目,鉴于团队技术栈,选型.net core + vue,前后端分离.本打算捡现成的轮子的,github上大致逛了逛,总发现这样那样的不太适合心中那些“完美实践”,例如:Ab ...
- Core + Vue 后台管理基础框架3——后端授权
1.前言 但凡业务系统,授权是绕不开的一环.见过太多只在前端做菜单及按钮显隐控制,但后端裸奔的,觉着前端看不到,系统就安全,掩耳盗铃也好,自欺欺人也罢,这里不做评论.在.NET CORE中,也见过不少 ...
- Core + Vue 后台管理基础框架4——前端授权
1.前言 上篇,我们讲了后端的授权.与后端不同,前端主要是通过功能入口如菜单.按钮的显隐来控制授权的.具体来讲,就是根据指定用户的制定权限来加载对应侧边栏菜单和页面内的功能按钮.我们一个个来讲. 2. ...
- Core + Vue 后台管理基础框架9——统一日志
1.背景 前阵子有园友留言,提到日志相关的东西,同时,最近圈子里也有提到日志这个东西.一个充分.集中的统一日志平台还是很有必要的,否则系统出问题了只能靠猜或者干瞪眼.何谓充分,日志记录满足最低要求.出 ...
- Core + Vue 后台管理基础框架7——APM
1.前言 APM,又称应用性能统计,主要用来跟踪请求调用链,每个环节调用耗时,为我们诊断系统性能.定位系统问题提供了极大便利.本系统采用的是Elastic Stack体系中的APM,主要是之前部门搞P ...
- Core + Vue 后台管理基础框架8——Swagger文档
1.前言 作为前后端分离的项目,或者说但凡涉及到对外服务的后端,一个自描述,跟代码实时同步的文档是极其重要的.说到这儿,想起了几年前在XX速运,每天写完代码,还要给APP团队更新文档的惨痛经历.给人家 ...
- Core + Vue 后台管理基础框架1——运行系统
1.down源码 git clone https://github.com/KINGGUOKUN/SystemManagement.git,项目目录如下: 2.还原数据库 找到项目根目录下System ...
- hsweb 企业后台管理基础框架
hsweb 详细介绍 业务功能 现在: 权限管理: 权限资源-角色-用户. 配置管理: kv结构,自定义配置.可通过此功能配置数据字典. 脚本管理: 动态脚本,支持javascript,groovy, ...
- 如何在ASP.NET Core中实现一个基础的身份认证
注:本文提到的代码示例下载地址> How to achieve a basic authorization in ASP.NET Core 如何在ASP.NET Core中实现一个基础的身份认证 ...
随机推荐
- as和强制类型转换的区别
之前一直以为as就是强制类型转换,只是as是AS3中新的语法,之前用在有继承关系的对象之间的转换也无甚区别,但是今天却让我领悟到了它俩之间的区别. 原起:今天要给ColorPicker控件动态赋值,它 ...
- Linux文件与目录管理,常用命令总结
绝对路径: 以根目录 / 开始的相对路径: 相对于当前路径的写法 $PATH: 可执行文件路径的变量(出现在该变量下的文件可以在系统的任何目录下都可以执行) 获取路径的文件名: basen ...
- 让一个div拖动和让一个panel拖动加拉大拉小
一.让一个div拖动 <!doctype html> <html xmlns="http://www.w3.org/1999/xhtml"> <hea ...
- hadoop-2.5.2 源码学习1
- mac命令日常总结
查看某个端口被占用 lsof -i tcp:8080 kill进程: 找到进程的PID,使用kill命令:kill -9 716(PID) date 显示系统日期 mkdir xx 创建xx目录 rm ...
- Nginx for windows 访问路径包含中文
转载自http://blog.csdn.net/five824/article/details/48261213 Nginx for windows 访问路径包含中文 原创 2015年09月07日 0 ...
- Stock Starer股票盯盘
一个业余小项目,用于监控指定股票的成交指标,触发事件的主动通知 源码 !https://github.com/jeffchen81/stock-starer 设计说明 场景 定时任务1:通过网上Ope ...
- linux记录每次登陆的历史命令
编辑/etc/profile,增加如下代码 #Record history operation USER_IP=`>/dev/null |awk '{print $NF}' |sed -e 's ...
- frp端口映射穿透内网
前言 frp 是一个高性能的反向代理应用,可以轻松地进行内网穿透,对外网提供服务,支持 TCP.UDP.HTTP.HTTPS 等协议类型,并且 web 服务支持根据域名进行路由转发. Github: ...
- Linux内核初探 之 进程(三) —— 进程调度算法
一.基本概念 抢占 Linux提供抢占式多任务,基于时间片和优先级对进程进行强制挂起 非抢占的系统需要进程自己让步(yielding) 进程类型 IO消耗型 经常处于可运行态,等待IO操作过程会阻塞 ...