如何检查数组或 Ocelot 网关中的任何声明值?

kvu*_*ong 4 asp.net-core api-gateway ocelot

假设我有 2 个这样的端点

  1. 创建订单:需要声明order_perm,其值在数组["order_create", "order_edit"]中
  2. 订单搜索:只需要声明order_perm存在

在情况 1 中,我将上面的数组传递给RouteClaimsRequirement,如下所示

"RouteClaimsRequirement": {
        "order_perm": ["order_create", "order_edit"]
      }
Run Code Online (Sandbox Code Playgroud)

但当应用程序启动时它会崩溃,并且在情况 2 中。我这样设置

"RouteClaimsRequirement": {
            "order_perm": ""
          }
Run Code Online (Sandbox Code Playgroud)

但用户声称“order_perm”:“create_order”授权失败。

RouteClaimsRequirement是否支持这些用例?如果是这样我该怎么做?

小智 5

我知道这是一个老问题,我最近陷入了同样的问题,经过大量谷歌搜索后,我在github上找到了这个解决方案。当我使用 Ocelot 16.0.1 时,我更改了一些内容以使其适合我。ocelot.json 文件

{
  "DownstreamPathTemplate": "/api/{everything}/{everything}",
  "DownstreamScheme": "http",
  "DownstreamHostAndPorts": [
    {
      "Host": "localhost",
      "Port": "80"
    }
  ],
  "UpstreamPathTemplate": "/web/{everything}/{everything}",
  "UpstreamHttpMethod": [ "GET" ],
  "AuthenticationOptions": {
    "AuthenticationProviderKey": "Authkey",
    "AllowedScopes": []
  },
  "RouteClaimsRequirement": {
    "Role": "Admin , SuperAdmin"
  },
  "SwaggerKey": "myapi"

},
Run Code Online (Sandbox Code Playgroud)

配置方法

public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //your code here
        var configration = new OcelotPipelineConfiguration
        {
            AuthorisationMiddleware=async (ctx, next) =>
            {
                if (this.Authorize(ctx))
                {
                    await next.Invoke();
                }
                else
                {
                    ctx.Items.SetError(new UnauthorisedError($"Fail to authorize"));
                }
            }
        };
        //your code here
        await app.UseOcelot(configration);
    }
Run Code Online (Sandbox Code Playgroud)

授权方式

 private bool Authorize(HttpContext ctx)
    {
        if (ctx.Items.DownstreamRoute().AuthenticationOptions.AuthenticationProviderKey == null) return true;
        else
        {

            bool auth = false;
            Claim[] claims = ctx.User.Claims.ToArray<Claim>();
            Dictionary<string, string> required = ctx.Items.DownstreamRoute().RouteClaimsRequirement;
            Regex reor = new Regex(@"[^,\s+$ ][^\,]*[^,\s+$ ]");
            MatchCollection matches;

            Regex reand = new Regex(@"[^&\s+$ ][^\&]*[^&\s+$ ]");
            MatchCollection matchesand;
            int cont = 0;
            foreach (KeyValuePair<string, string> claim in required)
            {
                matches = reor.Matches(claim.Value);
                foreach (Match match in matches)
                {
                    matchesand = reand.Matches(match.Value);
                    cont = 0;
                    foreach (Match m in matchesand)
                    {
                        foreach (Claim cl in claims)
                        {
                            if (cl.Type == claim.Key)
                            {
                                if (cl.Value == m.Value)
                                {
                                    cont++;
                                }
                            }
                        }
                    }
                    if (cont == matchesand.Count)
                    {
                        auth = true;
                        break;
                    }
                }
            }
            return auth;
        }
    }
Run Code Online (Sandbox Code Playgroud)