ocelot 自定义认证和授权

原文:ocelot 自定义认证和授权

ocelot 自定义认证和授权

Intro

最近又重新启动了网关项目,服务越来越多,每个服务都有一个地址,这无论是对于前端还是后端开发调试都是比较麻烦的,前端需要定义很多 baseUrl,而后端需要没有代码调试的时候需要对每个服务的地址都收藏着或者记在哪里,用的时候要先找到地址,甚是麻烦,有了网关之后,所有的 API 就有了统一的入口,对于前端来说就不需要维护那么多的 baseUrl,只需要网关的地址即可,对于后端来说也是同样的。

Ocelot 简介

Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断等功能,这些功能只都只需要简单的配置即可完成。

自定义认证授权

自定义认证授权思想,这里的示例是一个基于用户角色授权的示例:

  1. 基于 url 以及 请求 Method 查询需要的权限
  2. 如果不需要用户登录就可以访问,就直接往下游服务转发
  3. 如果需要权限,判断当前登录用户的角色是否可以以当前 Method 访问当前路径
  4. 如果可以访问就转发到下游服务,如果没有权限访问根据用户是否登录,已登录返回 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

如果有什么问题或建议,欢迎提出一起交流

原文地址:https://www.cnblogs.com/lonelyxmas/p/10850718.html

时间: 2024-08-30 11:37:12

ocelot 自定义认证和授权的相关文章

Ocelot简易教程(五)之集成IdentityServer认证以及授权

原文:Ocelot简易教程(五)之集成IdentityServer认证以及授权 Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 Ocelot简易教程(四)之请求聚合以及服务发现 Ocelot简易教程(五)之集成IdentityServer认证以及授权 Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据 Ocelot简易教程(七)之配

SpringSecurity 3.2入门(10)自定义权限控制认证及授权的过程

上一章的代码实现还存在一些问题,如角色表.权限表的用处没有体现出来,但是已经能完成URL拦截功能,后面将会继续完善认证及授权的过程. 认证及授权的过程如下: 1.容器启动,MyInvocationSecurityMetadataSourceService类执行loadResourceDefine()方法,提取数据库中所有的资源,并将资源URL作为key,资源标识作为value,形成Map结构的数据. 2.用户发送请求,若该请求为设置不拦截属性,则MySecurityFilter类执行doFilt

asp.net core 自定义认证方式--请求头认证

原文:asp.net core 自定义认证方式--请求头认证 asp.net core 自定义认证方式--请求头认证 Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思路 网关可以做一部分的认证和授权,服务内部有时候也会需要用户的信息,这时该怎么办呢,我们使用的是 JWT 认证,有一个 identity server去颁发,验证 token,一种简单方式可以把 token 直接往后传,传递给后面的具体某

BOS项目 第7天(shiro权限框架进行认证和授权)

BOS项目笔记 第7天 今天内容安排: 1.权限概述(认证.授权) 2.常见的权限控制的方式(URL拦截权限控制.方法注解权限控制) 3.权限数据模型(权限表.角色表.用户表.角色权限关系表.用户角色关系表) 4.shiro框架入门 5.将shiro应用到bos项目中进行认证和授权 1. 权限概述 系统提供了很多功能,并不是所有的用户登录系统都可以操作这些功能.我们需要对用户的访问进行控制. 认证:系统提供的用于识别用户身份的功能(通常是登录功能)-----让系统知道你是谁?? 授权:系统提供的

Java Web系列:认证和授权基础

1.认证和授权概述 (1)认证:对用户的身份进行验证. .NET基于的RBS(参考1)的认证和授权相关的核心是2个接口System.Security.Principal.IPrincipal和System.Security.Principal.IIdentity.我们自己实现认证过程,通过Thread.CurrentPrincipal来设置和读取认证结果.认证成功后设置认证状态和标识. Java内置了的JAAS(参考2),核心是javax.security.auth.Subject类和javax

Apache Shiro 认证、授权、加密和会话管理

官方解释 : Apache Shiro(日语"堡垒(Castle)"的意思)是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用.移动应用到大型网络及企业应用. Shiro为解决下列问题(我喜欢称它们为应用安全的四要素)提供了保护应用的API: 认证 - 用户身份识别,常被称为用户"登录": 授权 - 访问控制: 密码加密 - 保护或隐藏数据防止被偷窥: 会话管理 - 每用户相关的时间敏感的状态. Shi

关于认证和授权

这里设计的内容比较多: cookie, form认证,request,response,IPriciple,Identity,menberhsip,claim,owin,middleware,asp.net mvc 5,还有oauth,openid, json web token相关的各种 加密,解密,秘钥,签名,数字证书,ssl 等等一些 关于认证和授权的各种信息: 关于form认证和自form认证的扩展: http://www.cnblogs.com/fish-li/archive/2012

Spring Security技术栈开发企业级认证与授权

Spring Security技术栈开发企业级认证与授权网盘地址:https://pan.baidu.com/s/1mj8u6JQ 密码: 92rp备用地址(腾讯微云):https://share.weiyun.com/8b2ffc1839069b4399950333860754a4 密码:a539tn 第1章 课程导学介绍课程内容.课程特点,使用的主要技术栈,以及学习课程所需的前置知识 第2章 开始开发安装开发工具,介绍项目代码结构并搭建,基本的依赖和参数设置,开发hello world 第3

【shiro】(4)---Shiro认证、授权案例讲解

Shiro认证.授权案例讲解 一.认证  1. 认证流程     2.用户密码已经加密.加盐的用户认证 (1)测试类 // 用户登陆和退出,这里我自定了一个realm(开发肯定需要自定义realm获取数据库密码和权限) @Test public void testCustomRealmMd5() { // 创建securityManager工厂,通过ini配置文件创建securityManager工厂 Factory<SecurityManager> factory = new IniSecu