身份认证传递

  对于Abp比较熟悉的朋友应该对他里面的用户身份认证比较熟悉,他是通过实现微软提供的权限认证方式实现的,用户登录身份信息存储在System.Security.Claims.ClaimsPrincipal里面,但是用户的身份信息如何在不同的服务之间传递呢,不可能每一个服务都必须实现这套身份认证吧?比如我们请求调用过程如下:

  Portal站点获取用户信息没有问题,但如何传递到调用的其他微服务呢?

  这在之前文章中提到的传输Header就起到了作用,有两种方式可以处理,第一种我们可以直接把accessToken信息放到header里面,传输到服务提供者处理,服务提供程序解析里面的accessToken,赋值给Microsoft.AspNetCore.Authentication.JwtBearer. MessageReceivedContext的Token属性,参照abp里面signalr部分的身份认证信息处理,但是这里有个问题,就是没一个服务宿主应用都需要实现微软的身份认证这套逻辑;另外一种方式,我们的用户信息既然已经解析出来了,那可以直接拿到值,直接通过传输Header,传递给服务提供者,服务提供者拿到Header之后,直接给Claims赋值,这样传输的内容会少一些,并且服务不需要实现微软身份认证这套逻辑,我这里直接采用的第二种方式实现,代码如下:

  客户端Invoke方法

var abpSession = Dependency.IocManager.Instance.Resolve<IAbpSession>();
if (!string.IsNullOrEmpty(abpSession.AccessToken)) // 将用户Token转递到其他微服务
{
contextNameValueCollection.Add("AccessToken", "1");
contextNameValueCollection.Add("UserId", abpSession.UserId?.ToString());
contextNameValueCollection.Add("UserName", abpSession.UserName);
contextNameValueCollection.Add("TenantId", abpSession.TenantId?.ToString());
contextNameValueCollection.Add("RoleIds", abpSession.RoleIds); }
var jsonRespStr = LocalRpcRun(jsonReqStr, contextNameValueCollection);

  服务端JsonRpcProcessor类方法

public static Task<string> Process(string sessionId, string jsonRpc, object context = null)
{
return Task<string>.Factory.StartNew((_) =>
{
if ((context is Newtonsoft.Json.Linq.JObject) && (context as Newtonsoft.Json.Linq.JObject)["AccessToken"] != null) // 设置Token
{
var identity = new ClaimsIdentity();
var accessToken = ((Newtonsoft.Json.Linq.JValue)(context as Newtonsoft.Json.Linq.JObject)["AccessToken"]).Value;
var userId = ((Newtonsoft.Json.Linq.JValue)(context as Newtonsoft.Json.Linq.JObject)["UserId"])?.Value;
var tenantId = ((Newtonsoft.Json.Linq.JValue)(context as Newtonsoft.Json.Linq.JObject)["TenantId"])?.Value;
var roleIds = ((Newtonsoft.Json.Linq.JValue)(context as Newtonsoft.Json.Linq.JObject)["RoleIds"])?.Value;
var userName = ((Newtonsoft.Json.Linq.JValue)(context as Newtonsoft.Json.Linq.JObject)["UserName"])?.Value; if(userId != null) identity.AddClaim(new Claim(AbpClaimTypes.UserId, userId?.ToString()));
if (tenantId != null) identity.AddClaim(new Claim(AbpClaimTypes.TenantId, tenantId?.ToString()));
if (roleIds != null) identity.AddClaim(new Claim(AbpClaimTypes.RoleIds, roleIds?.ToString()));
if (userName != null) identity.AddClaim(new Claim(AbpClaimTypes.UserName, userName?.ToString()));
if (accessToken != null) identity.AddClaim(new Claim(AbpClaimTypes.AccessToken, accessToken.ToString()));
Thread.CurrentPrincipal = new ClaimsPrincipal(identity);
}
if (context is NameValueCollection)
{
var namevalues = context as NameValueCollection;
if(Thread.CurrentPrincipal == null && !string.IsNullOrEmpty(namevalues.Get("AccessToken")))
{
var identity = new ClaimsIdentity();
var accessToken = namevalues.Get("AccessToken");
var userId = namevalues.Get("UserId");
var tenantId = namevalues.Get("TenantId");
var roleIds = namevalues.Get("RoleIds");
var userName = namevalues.Get("UserName"); if (userId != null) identity.AddClaim(new Claim(AbpClaimTypes.UserId, userId?.ToString()));
if (tenantId != null) identity.AddClaim(new Claim(AbpClaimTypes.TenantId, tenantId?.ToString()));
if (roleIds != null) identity.AddClaim(new Claim(AbpClaimTypes.RoleIds, roleIds?.ToString()));
if (userName != null) identity.AddClaim(new Claim(AbpClaimTypes.UserName, userName?.ToString()));
if (accessToken != null) identity.AddClaim(new Claim(AbpClaimTypes.AccessToken, accessToken.ToString()));
Thread.CurrentPrincipal = new ClaimsPrincipal(identity);
}
} var tuple = (Tuple<string, string, object>)_;
return ProcessInternal(tuple.Item1, tuple.Item2, tuple.Item3);
}, new Tuple<string, string, object>(sessionId, jsonRpc, context));
}

请求处理拦截

  Abp里面的拦截起点部分在ActionFilter里面,但是微服务调用没有经过ActionFilter的拦截,所以这部分需要添加到微服务处理过程中,同样是对直接调用方法的拦截,直接把代码迁移过来就可以了。

  代码片段如下:

try
{
// 验证权限
var authorizationHelper = Dependency.IocManager.Instance.Resolve<IAuthorizationHelper>();
authorizationHelper.AuthorizeAsync(mothod.First(), mothod.First().DeclaringType).Wait();
}
catch(AbpAuthorizationException ex)
{
JsonResponse response = new JsonResponse()
{
Result = null,
Error = new JsonRpcException(-32600, "Authorize error", "The user has not permiss to " + Rpc.Method + ".", Rpc),
Id = Rpc.Id
};
callback.Invoke(response);
CompletedProcess(Rpc, response, RpcContext);
return response;
} var _unitOfWorkDefaultOptions = Dependency.IocManager.Instance.Resolve<IUnitOfWorkDefaultOptions>();
var _unitOfWorkManager = Dependency.IocManager.Instance.Resolve<IUnitOfWorkManager>();
var unitOfWorkAttr = _unitOfWorkDefaultOptions.GetUnitOfWorkAttributeOrNull(mothod.First()); object results; if (!unitOfWorkAttr.IsDisabled)
{
using (var uow = _unitOfWorkManager.Begin(unitOfWorkAttr.CreateOptions()))
{
results = newDel.DynamicInvoke(parameters);
uow.Complete();
}
}
else
{
results = newDel.DynamicInvoke(parameters);
}

企业级工作流解决方案(六)--微服务消息处理模型之与Abp集成的更多相关文章

  1. 【微服务专题之】.Net6下集成消息队列上-RabbitMQ

    ​ 微信公众号:趣编程ACE关注可了解更多的.NET日常实战开发技巧,如需源码 请公众号后台留言 源码;[如果觉得本公众号对您有帮助,欢迎关注] .Net中RabbitMQ的使用 [微服务专题之].N ...

  2. 企业级工作流解决方案(八)--微服务Tcp消息传输模型之服务端处理

    服务端启动 服务端启动主要做几件事情,1. 从配置文件读取服务配置(主要是服务监听端口和编解码配置),2. 注册编解码器工厂,3. 启动dotnetty监听端口,4. 读取配置文件,解析全局消息处理模 ...

  3. 企业级工作流解决方案(十一)--集成Abp和ng-alain--权限系统服务

    权限系统主要定义为管理员增删改查权限数据,直接读取数据库,权限系统服务主要定义为供其他系统调用的权限验证接口,定义为两个不同的微服务. 权限系统有一个特点,数据变动比较小,数据量本身并不是很大,访问量 ...

  4. .NET Core 中的 Swagger 应用与微服务场景下的Swagger Api 集成显示

    Swagger 与 OpenAPI 的历史来源: Swagger 项目于 2015 年捐赠给 OpenAPI Initiative,此后被称为 OpenAPI.这两个名称可以互换使用.但是," ...

  5. 微服务:springboot与swagger2的集成

    现在测试都提倡自动化测试,那我们作为后台的开发人员,也得进步下啊,以前用postman来测试后台接口,那个麻烦啊,一个字母输错就导致测试失败,现在swagger的出现可谓是拯救了这些开发人员,便捷之处 ...

  6. 企业级工作流解决方案(九)--微服务Tcp消息传输模型之客户端处理

    客户端启动 客户端启动主要做三件事情,1. 从配置文件读取服务调用配置,存储到全局对象中.2. 指定客户端编解码器工厂.3. 预连接,即预先建立与服务端的通信Chanel. [DependsOn(ty ...

  7. 企业级工作流解决方案(七)--微服务Tcp消息传输模型之消息编解码

    Tcp消息传输主要参照surging来做的,做了部分裁剪和改动,详细参见:https://github.com/dotnetcore/surging Json-rpc没有定义消息如何传输,因此,Jso ...

  8. 企业级工作流解决方案(十四)--集成Abp和ng-alain--自动化脚本

    对于.net方向,做过自动化的,应该没有人不熟悉msbuild吧,非常强大的代码编译工具,.net平台的编译工作都是交给他来完成的,包括.net core的命令,本质上都是调用msbuild来执行的 ...

  9. 企业级工作流解决方案(十五)--集成Abp和ng-alain--Abp其他改造

    配置功能增强 Abp定义了各种配置接口,但是没有定义这些配置数据从哪里来,但是管理配置数据对于一个应用程序来说,是必不可少的一件事情. .net的配置数据管理,一般放在Web.config文件或者Ap ...

随机推荐

  1. 【应用服务 App Service】App Service 中部署Java应用中文乱码现象

    问题情形 有时候部署在 Azure  App Service的 Java应用会出现乱码 详细日志 无 问题原因 因为 App Service默认的编码为gbk,所以在显示页面或传递中文字符时就会出现乱 ...

  2. Mybatis---01Mybatis动态代理过程分析

    1.通过调试,session调用的getMapper是其实现类DefaultSQLSession中的 //1.读取配置文件 InputStream in = Resources.getResource ...

  3. SQL注入的一些学习

    -------------------------------------- 这是我之前发布到的其他的一个网址,这里的话我重新总结 可能分很多,我也不是很清楚,只是皮毛的研究了一下 1,sql按数据库 ...

  4. 关于transition中嵌套keep-alive的问题解决

    需求:在使用keep-alive的同时使用transition动画效果 最开始是这样写的,但是发现报错,而且动画效果失效 <transition name="container-rig ...

  5. 03 . Go框架之Gin框架从入门到熟悉(Cookie和Session,数据库操作)

    Cookie Cookie是什么 HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出 Cookie就是解决HTTP协议无状态的方案之一,中文是小 ...

  6. 03 . Gin+Vue开发一个线上外卖应用(用户数据创建,插入,跨域处理)

    功能和背景介绍 在项目的登录功能中,如果在登录时发现用户名和密码在用户表中不存在,会自动将用户名和密码保存在用户表中,创建一个新的用户. 因此,除了使用手机号和验证码登录以外,还支持使用用户名.密码进 ...

  7. Reverse for ‘password_reset_complete‘ not found. ‘password_reset_complete‘ is not a valid view funct

    关注公众号"轻松学编程"了解更多 原因 在使用xadmin与django 2版本以上修改密码时会报这个错,这是由于django修改密码成功后使用的是success_url参数,而x ...

  8. 利用VS2017制作软件安装包与卸载程序

    本博客讲述如何利用VS2017制作安装包以及相应的卸载程序,并解决过程中可能遇到的问题 一.制作安装程序 1.打开VS2017,新建项目,选择如下图所示程序: 新建成功后,会出现如下图所示目录: 2. ...

  9. 5.MVCC

    5 MVCC ​ 全称是Multi-Version Concurrent Control,即多版本并发控制,在MVCC协议下,每个读操作会看到一个一致性的snapshot,并且可以实现非阻塞的读.MV ...

  10. Java项目——嗖嗖移动业务大厅

    嗖嗖移动业务大厅包类(如下图): SosoMgr: 1 package cn.biz; 2 3 import java.util.Scanner; 4 5 import cn.common.Commo ...