中间件
WebHost,请求进来,ProcessRequest,request请求出来,先经过下列中间件,由next(context)层层传递,再response返回
app.UseCorrelationId()
request: request没有header,则返回一个Guid.NewGuid().ToString("N"),若有取Headers【X-Correlation-Id】,若非空则返回,否则生成一个,给header设置一个头,则返回此头
response:检查并确定给response返回一个correlationId
app.UseVirtualFiles();
提供静态文件StaticFileOptions.FileProvider
app.UseAbpRequestLocalization();
获取RequestLocalizationOptions,并执行LocalizationOptions的委托 IAbpRequestLocalizationOptionsProvider.InitLocalizationOptions
创建RequestLocalizationMiddleware,导入LocalizationOptions和_loggerFactory
app.UseRouting();
public static IApplicationBuilder UseRouting(this IApplicationBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } VerifyRoutingServicesAreRegistered(builder); var endpointRouteBuilder = new DefaultEndpointRouteBuilder(builder); builder.Properties[EndpointRouteBuilder] = endpointRouteBuilder; return builder.UseMiddleware<EndpointRoutingMiddleware>(endpointRouteBuilder); }
{ // There's already an endpoint, skip maching completely var endpoint = httpContext.GetEndpoint(); if (endpoint != null) { Log.MatchSkipped(_logger, endpoint); return _next(httpContext); } // There's an inherent race condition between waiting for init and accessing the matcher // this is OK because once `_matcher` is initialized, it will not be set to null again. var matcherTask = InitializeAsync(); if (!matcherTask.IsCompletedSuccessfully) { return AwaitMatcher(this, httpContext, matcherTask); } var matchTask = matcherTask.Result.MatchAsync(httpContext); if (!matchTask.IsCompletedSuccessfully) { return AwaitMatch(this, httpContext, matchTask); } return SetRoutingAndContinue(httpContext); // Awaited fallbacks for when the Tasks do not synchronously complete static async Task AwaitMatcher(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task<Matcher> matcherTask) { var matcher = await matcherTask; await matcher.MatchAsync(httpContext); await middleware.SetRoutingAndContinue(httpContext); } static async Task AwaitMatch(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task matchTask) { await matchTask; await middleware.SetRoutingAndContinue(httpContext); } }
app.UseAuthentication();
创建HttpContext.User,Abp Vnext提供的ICurrentUser就是来源HttpContext.User?Thead.ClaimsPrincipals
public async Task Invoke(HttpContext context) { context.Features.Set<IAuthenticationFeature>(new AuthenticationFeature { OriginalPath = context.Request.Path, OriginalPathBase = context.Request.PathBase }); // Give any IAuthenticationRequestHandler schemes a chance to handle the request var handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { var handler = await handlers.GetHandlerAsync(context, scheme.Name) as IAuthenticationRequestHandler; if (handler != null && await handler.HandleRequestAsync()) { return; } } var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await context.AuthenticateAsync(defaultAuthenticate.Name); if (result?.Principal != null) { context.User = result.Principal; } } await _next(context); }
app.UseMiddleware<FakeAuthenticationMiddleware>();
认证:提供一个fake
new ClaimsIdentity(_fakeUserClaims.Claims, "FakeSchema")
app.UseAuthorization();
public async Task Invoke(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var endpoint = context.GetEndpoint(); if (endpoint != null) { // EndpointRoutingMiddleware uses this flag to check if the Authorization middleware processed auth metadata on the endpoint. // The Authorization middleware can only make this claim if it observes an actual endpoint. context.Items[AuthorizationMiddlewareInvokedWithEndpointKey] = AuthorizationMiddlewareWithEndpointInvokedValue; } // IMPORTANT: Changes to authorization logic should be mirrored in MVC's AuthorizeFilter var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>(); var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData); if (policy == null) { await _next(context); return; } // Policy evaluator has transient lifetime so it fetched from request services instead of injecting in constructor var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>(); var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context); // Allow Anonymous skips all authorization if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null) { await _next(context); return; } // Note that the resource will be null if there is no matched endpoint var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, context, resource: endpoint); if (authorizeResult.Challenged) { if (policy.AuthenticationSchemes.Any()) { foreach (var scheme in policy.AuthenticationSchemes) { await context.ChallengeAsync(scheme); } } else { await context.ChallengeAsync(); } return; } else if (authorizeResult.Forbidden) { if (policy.AuthenticationSchemes.Any()) { foreach (var scheme in policy.AuthenticationSchemes) { await context.ForbidAsync(scheme); } } else { await context.ForbidAsync(); } return; } await _next(context); }
app.UseAuditing();
判断请求是否需要写审计log =》可配置,不允许匿名访问而且用户没有认证 不审计, get请求不写审记
需要的话,创建一个IAuditLogSaveHandle,
response: 保存 scope.SaveAsync()
app.UseUnitOfWork();
1、先创建一个AbpExceptionHandlingMiddleware
如果出错,则catch到错误,并返回错误
2、工作单元中间件:
创建一个Reserve的保留工作单元
在AbpUowActionFilter,则启用工作单元
private static void AddFilters(MvcOptions options) { options.Filters.AddService(typeof(AbpAuditActionFilter)); options.Filters.AddService(typeof(AbpFeatureActionFilter)); options.Filters.AddService(typeof(AbpValidationActionFilter)); options.Filters.AddService(typeof(AbpUowActionFilter)); options.Filters.AddService(typeof(AbpExceptionFilter)); }
app.UseMvcWithDefaultRouteAndArea();
首先经过路由规则的匹配,找到最符合条件的的IRouter,然后调用IRouter.RouteAsync来设置RouteContext.Handler,最后把请求交给RouteContext.Handler来处理。
在MVC中提供了两个IRouter实现,分别如下:MvcAttributeRouteHandler,MvcRouteHandler
ApplicationModel->ControllerModel->ActionModel
通过路由和动作匹配后,最终会得到跟当前请求最匹配的一个ActionDescriptor,然后通过IActionInvoker执行动作。
创建Action,由IActionInvokerFactory负责创建,
依赖ILoggerFactory,
SaveTempDataFilter
AbpAuditActionFilter 》需要用户,租户,时间,序列化,客户端等服务支持
只处理ControllerAction
AbpFeatureActionFilter
只处理ControllerAction,不处理
AbpValidationActionFilter
AbpUowActionFilter
AbpExceptionFilter 》IExceptionToErrorInfoConverter,IHttpExceptionStatusCodeFinder,IJsonSerializer
再创建
FeatureTestController (目标)
由于此服务注册了拦截器Feature,由于拦截器负责代理
ProcessRequest(WebHost)
RequestServicesContainerMiddleware:给请求上下文绑定容器,它所做的事情就是创建一个范围内的服务提供者并在请求结束时销毁它,当全部的Middleware都被执行完后,并返回到了RequestServiceContainerMiddleware,Scoped Container会被销毁通过"Using"
HostFilteringMiddleware
ForwardHeaderMiddleWare
IISMiddleWare