Ocelot 自定义权限中间件,自定义中间件添加


1.定义中间件:(示例代码,不全)

using Dx.Csp.Infrastructure;
using Dx.Csp.Infrastructure.Enums;
using Dx.Csp.RoleManage;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Ocelot.Authorisation;
using Ocelot.Errors;
using Ocelot.Logging;
using Ocelot.Middleware;
using Ocelot.Responses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dx.Csp.PermissionManage;
using Dx.Csp.AccountNoManage;
using Dx.Csp.QualificationManage;
using Dx.Csp.Infrastructure.Result;

namespace Dx.CspGateway.Middleware
{
    public class AuthorizationCustomMiddleware : OcelotMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IClaimsAuthoriser _claimsAuthoriser;
        private readonly IScopesAuthoriser _scopesAuthoriser;
        private IUrlAscriptionPermissionService _urlAscriptionPermissionService;
        private IRoleManageService _roleManageService;
        private IAccountNoManageService _accountNoManageService;
        private IConfiguration _configuration;
        private IBusinessQualificationsService _businessQualificationsService;
        public AuthorizationCustomMiddleware(
             IOcelotLoggerFactory loggerFactory,
            RequestDelegate next,
            IClaimsAuthoriser claimsAuthoriser,
            IScopesAuthoriser scopesAuthoriser,
            IUrlAscriptionPermissionService urlAscriptionPermissionService,
            IRoleManageService roleManageService,
            IAccountNoManageService accountNoManageService,
            IBusinessQualificationsService businessQualificationsService,
            IConfiguration configuration
            ) : base(loggerFactory.CreateLogger())
        {
            _businessQualificationsService = businessQualificationsService;
            _accountNoManageService = accountNoManageService;
            _urlAscriptionPermissionService = urlAscriptionPermissionService;
            _next = next;
            _claimsAuthoriser = claimsAuthoriser;
            _scopesAuthoriser = scopesAuthoriser;
            _roleManageService = roleManageService;
            _configuration = configuration;
        }
        public async Task Invoke(HttpContext httpContext)
        {
            var downstreamRequest = httpContext.Items.DownstreamRequest();
            var downstreamReRoute = httpContext.Items.DownstreamRoute();
            //检查是否认证
            if (!httpContext.User.Identity.IsAuthenticated)
            {
                //检查是否为注册,登录,验证码等不需要进行鉴权的url,否直接响应失败
                await IsNotAuthenticated(httpContext, downstreamRequest);
                return;
            }
            //检查账号状态
            if (!await CheckAccountAsync(httpContext))
            {
                httpContext.Items.UpsertErrors(new List { new UnauthorisedError($"账号停用") });
                return;
            }
            //获取客户信息检查,运营平台,管理平台
            var ascription = httpContext.User.Claims.SingleOrDefault(c => c.Type == ClaimNameTypes.Ascription).Value;
            var accountAscription = (AccountAscription)Convert.ToInt32(ascription);
            if (accountAscription == AccountAscription.OperationPlatform)//运营平台
            {
                await OperationAuthrazition(httpContext, downstreamRequest);
                return;
            }
            //管理平台
            await ManageAuthrazition(httpContext, downstreamRequest);
            return;
        }
       
    }
}

2.定义扩展方法

using Dx.CspGateway.Middleware;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Dx.Csp.OcelotGateway
{
    public static class AuthorizationCustomMiddlewareExtensions
    {
        public static IApplicationBuilder UseAuthorizationCustom(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware();
        }
        public static void UseIfNotNull(this IApplicationBuilder builder,
            Func, Task> middleware)
        {
            if (middleware != null)
            {
                builder.Use(middleware);
            }
        }
    }
}

3.使用Ocelot

app.UseOcelot((builder, pipelineConfiguration) => {
                builder.UseDownstreamContextMiddleware();

                // This is registered to catch any global exceptions that are not handled
                // It also sets the Request Id if anything is set globally
                builder.UseExceptionHandlerMiddleware();

                // If the request is for websockets upgrade we fork into a different pipeline
                builder.MapWhen(httpContext => httpContext.WebSockets.IsWebSocketRequest,
                    wenSocketsApp =>
                    {
                        wenSocketsApp.UseDownstreamRouteFinderMiddleware();
                        wenSocketsApp.UseMultiplexingMiddleware();
                        wenSocketsApp.UseDownstreamRequestInitialiser();
                        wenSocketsApp.UseLoadBalancingMiddleware();
                        wenSocketsApp.UseDownstreamUrlCreatorMiddleware();
                        wenSocketsApp.UseWebSocketsProxyMiddleware();
                    });

                // Allow the user to respond with absolutely anything they want.
                builder.UseIfNotNull(pipelineConfiguration.PreErrorResponderMiddleware);

                // This is registered first so it can catch any errors and issue an appropriate response
                builder.UseResponderMiddleware();

                // Then we get the downstream route information
                builder.UseDownstreamRouteFinderMiddleware();

                // Multiplex the request if required
                builder.UseMultiplexingMiddleware();

                // This security module, IP whitelist blacklist, extended security mechanism
                builder.UseSecurityMiddleware();

                //Expand other branch pipes
                if (pipelineConfiguration.MapWhenOcelotPipeline != null)
                {
                    foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)
                    {
                        // todo why is this asking for an app app?
                        app.MapWhen(pipeline.Key, pipeline.Value);
                    }
                }

                // Now we have the ds route we can transform headers and stuff?
                builder.UseHttpHeadersTransformationMiddleware();

                // Initialises downstream request
                builder.UseDownstreamRequestInitialiser();

                // We check whether the request is ratelimit, and if there is no continue processing
                builder.UseRateLimiting();

                // This adds or updates the request id (initally we try and set this based on global config in the error handling middleware)
                // If anything was set at global level and we have a different setting at re route level the global stuff will be overwritten
                // This means you can get a scenario where you have a different request id from the first piece of middleware to the request id middleware.
                builder.UseRequestIdMiddleware();

                // Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
                builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware);

                // Now we know where the client is going to go we can authenticate them.
                // We allow the ocelot middleware to be overriden by whatever the
                // user wants
                if (pipelineConfiguration.AuthenticationMiddleware == null)
                {
                    app.UseAuthenticationMiddleware();
                }
                else
                {
                    app.Use(pipelineConfiguration.AuthenticationMiddleware);
                }

                // The next thing we do is look at any claims transforms in case this is important for authorisation
                builder.UseClaimsToClaimsMiddleware();

                // Allow pre authorisation logic. The idea being people might want to run something custom before what is built in.
                builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);

                // Now we have authenticated and done any claims transformation we
                // can authorise the request
                // We allow the ocelot middleware to be overriden by whatever the
                // user wants
                if (pipelineConfiguration.AuthorisationMiddleware == null)
                {
                    builder.UseAuthorisationMiddleware();
                }
                else
                {
                    builder.Use(pipelineConfiguration.AuthorisationMiddleware);
                }

                // Now we can run the claims to headers transformation middleware
                builder.UseClaimsToHeadersMiddleware();

                // Allow the user to implement their own query string manipulation logic
                builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware);

                // Now we can run any claims to query string transformation middleware
                builder.UseClaimsToQueryStringMiddleware();

                builder.UseClaimsToDownstreamPathMiddleware();

                // Get the load balancer for this request
                builder.UseLoadBalancingMiddleware();

                // This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
                builder.UseDownstreamUrlCreatorMiddleware();

                // Not sure if this is the best place for this but we use the downstream url
                // as the basis for our cache key.
                builder.UseOutputCacheMiddleware();
                builder.UseAuthorizationCustom();
                //注意UseAuthorizationCustom为自己定义中间件,必须放在UseHttpRequesterMiddleware上方,
                //否则请求是先走url对应的程序而后才会走自定义中间件
                //We fire off the request and set the response on the scoped data repo
                builder.UseHttpRequesterMiddleware();
                
                builder.Build();
            }).Wait();

4.以上除自定义中间件外,均由UseOcelot()源码中复制而来;