ocelot 自定义认证和授权
ocelot 自定义认证和授权
Intro
最近又重新启动了网关项目,服务越来越多,每个服务都有一个地址,这无论是对于前端还是后端开发调试都是比较麻烦的,前端需要定义很多 baseUrl,而后端需要没有代码调试的时候需要对每个服务的地址都收藏着或者记在哪里,用的时候要先找到地址,甚是麻烦,有了网关之后,所有的 API 就有了统一的入口,对于前端来说就不需要维护那么多的 baseUrl,只需要网关的地址即可,对于后端来说也是同样的。
Ocelot 简介
Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断等功能,这些功能只都只需要简单的配置即可完成。
自定义认证授权
自定义认证授权思想,这里的示例是一个基于用户角色授权的示例:
- 基于 url 以及 请求 Method 查询需要的权限
- 如果不需要用户登录就可以访问,就直接往下游服务转发
- 如果需要权限,判断当前登录用户的角色是否可以以当前 Method 访问当前路径
- 如果可以访问就转发到下游服务,如果没有权限访问根据用户是否登录,已登录返回 403 Forbidden,未登录返回 401 Unauthorized
Ocelot 的 认证授权不能满足我的需要,于是就自己扩展了一个 Ocelot 的中间件
示例代码
public class ApiPermission
{
public string AllowedRoles { get; set; }
public string PathPattern { get; set; }
public string Method { get; set; }
}
public class UrlBasedAuthenticationMiddleware : Ocelot.Middleware.OcelotMiddleware
{
private readonly IConfiguration _configuration;
private readonly IMemoryCache _memoryCache;
private readonly OcelotRequestDelegate _next;
public UrlBasedAuthenticationMiddleware(OcelotRequestDelegate next, IConfiguration configuration, IMemoryCache memoryCache, IOcelotLoggerFactory loggerFactory) : base(loggerFactory.CreateLogger<UrlBasedAuthenticationMiddleware>())
{
_next = next;
_configuration = configuration;
_memoryCache = memoryCache;
}
public async Task Invoke(DownstreamContext context)
{
var permissions = await _memoryCache.GetOrCreateAsync("ApiPermissions", async entry =>
{
using (var conn = new SqlConnection(_configuration.GetConnectionString("ApiPermissions")))
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
return (await conn.QueryAsync<ApiPermission>("SELECT * FROM dbo.ApiPermissions")).ToArray();
}
});
var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);
context.HttpContext.User = result.Principal;
var user = context.HttpContext.User;
var request = context.HttpContext.Request;
var permission = permissions.FirstOrDefault(p =>
request.Path.Value.Equals(p.PathPattern, StringComparison.OrdinalIgnoreCase) && p.Method.ToUpper() == request.Method.ToUpper());
if (permission == null)// 完全匹配不到,再根据正则匹配
{
permission =
permissions.FirstOrDefault(p =>
Regex.IsMatch(request.Path.Value, p.PathPattern, RegexOptions.IgnoreCase) && p.Method.ToUpper() == request.Method.ToUpper());
}
if (!user.Identity.IsAuthenticated)
{
if (permission != null && string.IsNullOrWhiteSpace(permission.AllowedRoles)) //默认需要登录才能访问
{
//context.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "Anonymous") }, context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey));
}
else
{
SetPipelineError(context, new UnauthenticatedError("unauthorized, need login"));
return;
}
}
else
{
if (!string.IsNullOrWhiteSpace(permission?.AllowedRoles) &&
!permission.AllowedRoles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Any(r => user.IsInRole(r)))
{
SetPipelineError(context, new UnauthorisedError("forbidden, have no permission"));
return;
}
}
await _next.Invoke(context);
}
}
认证授权之后
经过上面的认证授权之后,就可以往下游转发请求了,下游的服务有的可能会需要判断用户的角色或者需要根据用户的 userId 或者 Name 或者 邮箱去检查某些数据的权限,这里就需要把在网关完成认证之后,得到的用户信息传递给下游服务,这里我选择的是通过请求头把用户信息从网关服务传递到下游服务, Ocelot 可以把 Claims 中的信息转换到 Header ,详细参考Ocelot文档,但是实现有个bug,如果有多个值他只会取第一个,详见issue,可以自己扩展一个 ocelot 的中间件替换掉原有的中间件。
传递到下游服务之后,下游服务在需要用户信息的地方就可以从请求头中获取用户信息,如果下游服务比较复杂,不方便改动的话可以实现一个自定义的请求头认证,可以参考我的这一篇文章
Memo
如果有什么问题或建议,欢迎提出一起交流
ocelot 自定义认证和授权的更多相关文章
- spring security 3 自定义认证,授权示例
1,建一个web project,并导入所有需要的lib. 2,配置web.xml,使用Spring的机制装载: <?xml version="1.0" encoding=& ...
- 最简实例演示asp.net5中用户认证和授权(4)
上篇: 最简实例演示asp.net5中用户认证和授权(3) 上面我们把自定义认证和授权的相关的最小基础类和要实现的接口都实现了,下面就是如何来进行认证和授权的配置. 首先我们要告诉系统,我们的用户和角 ...
- Shiro 自定义登陆、授权、拦截器
Shiro 登陆.授权.拦截 按钮权限控制 一.目标 Maven+Spring+shiro 自定义登陆.授权 自定义拦截器 加载数据库资源构建拦截链 使用总结: 1.需要设计的数据库:用户.角色.权限 ...
- Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(四)
在上一讲中,我们已经完成了一个完整的案例,在这个案例中,我们可以通过Angular单页面应用(SPA)进行登录,然后通过后端的Ocelot API网关整合IdentityServer4完成身份认证.在 ...
- Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(一)
好吧,这个题目我也想了很久,不知道如何用最简单的几个字来概括这篇文章,原本打算取名<Angular单页面应用基于Ocelot API网关与IdentityServer4+ASP.NET Iden ...
- Ocelot简易教程(五)之集成IdentityServer认证以及授权
Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 ...
- spring-security-4 (5)spring security Java配置实现自定义表单认证与授权
前面三篇讲解了spring security的搭建以及简单的表单认证与授权原理.本篇将实现我们自定义的表单登录与认证. 本篇不会再讲项目的搭建过程,因为跟第二节的搭建如出一辙.本篇也不会将项目中所有 ...
- Ocelot(四)- 认证与授权
Ocelot(四)- 认证与授权 作者:markjiang7m2 原文地址:https://www.cnblogs.com/markjiang7m2/p/10932805.html 源码地址:http ...
- [转载]Ocelot简易教程(五)之集成IdentityServer认证以及授权
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9807125.html 最近比较懒,所以隔了N天才来继续更新第五篇Ocelot简易教程,本篇教程会先简单介 ...
随机推荐
- Asp.Net Core 轻松学-多线程之Task快速上手
前言 Task是从 .NET Framework 4 开始引入的一项基于队列的异步任务(TAP)模式,从 .NET Framework 4.5 开始,任何使用 async/await 进行修饰 ...
- Eclipse4JavaEE安装Gradle,并导入我们的Gradle项目
第一步:下载Gradle Gradle下载链接,如下图,下载最新版本即可.下载下来的zip包,解压到一个目录即可,如F盘 第二步:配置环境变量 首先添加GRADLE_HOME,如下图 然后在Path下 ...
- JDBC:SqlServer连接TCP/IP连接失败,到主机 的 TCP/IP 连接失败。报错信息:com.microsoft.sqlserver.jdbc.SQLServerException: 到主机 的 TCP/IP 连接失败。
作者QQ:1161493927,欢迎互相交流学习. 报错信息:com.microsoft.sqlserver.jdbc.SQLServerException: 到主机 的 TCP/IP 连接失败. j ...
- 关于bootstrap报错
在使用bootstrap报错.报错的位置如下 if("undefined"==typeof jQuery)throw new Error("Bootstrap's Jav ...
- 最简单的Nginx讲解--HTTP服务器、正向代理、反向代理、负载均衡
1. Nginx 1.1 Nginx简介 Nginx是俄罗斯人开发,开源的,免费的. Nginx功能: 1) nginx作为http服务器:类似apache,tomcat,遵循http协议. a) 访 ...
- Linux如何管理文档多租户
例题 同一群组microsoft下的两个账号justmine001和justmine002需要共同拥有目录/microsoft/eshop的开发权,以便进行协同工作,但是其他人不允许进入和查阅该目录. ...
- Scrapy-redis<数据库篇>
scrapy-redis爬虫数据库连接部分——windows准备做salve,Linux准备做master开展工作 首先处理简单的windows熟悉的环境——安装Redis服务和Redis可视化~可视 ...
- 网络协议 15 - P2P 协议:小种子大学问
[前五篇]系列文章传送门: 网络协议 10 - Socket 编程(上):实践是检验真理的唯一标准 网络协议 11 - Socket 编程(下):眼见为实耳听为虚 网络协议 12 - HTTP 协议: ...
- Python爬虫入门教程 49-100 Appium安装+操作51JOB_APP(模拟手机操作之一)手机APP爬虫
爬前准备工作 在开始安装Appium之前,你要先知道Appium是做什么的?Appium 是一个自动化测试开源工具,看到没,做测试用的,它有点类似Selenium,可以自动操作APP实现一系列的操作. ...
- 几个常用的vscode插件
1.Vetur 可以对.vue文件格式做语法高亮,开发基于Vue项目的标配插件 2.Power Mode 在写代码时出现如烟花.粒子.火焰之类的效果,增加写代码的乐趣 3.Chinese (simpl ...