首页 > 解决方案 > 从 .net core 2.2 迁移到 3.0 => 在 Authenticaton 之前执行授权

问题描述

几天前,我决定将我的应用程序从 .net core 2.2 迁移到 .net core 3.0 我面临的问题是,尽管按照中间件迁移的官方文档以正确的顺序订购了 app.Use..授权发生在认证之前。

这是我在 Startup 类中的 ConfigureServices 方法:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddApplicationInsightsTelemetry(settings.AppInsightsConnection);
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => false;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddSingleton(Log.Logger);
        services.AddSingleton(settings);
        services.AddHttpContextAccessor();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
            .AddCookie("Cookies", options => options.AccessDeniedPath = "/users/denied")
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";

                options.Authority = settings.Authority;
                options.ClientId = settings.ClientId;
                options.ClientSecret = settings.ClientSecret;
                options.ResponseType = "code";
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.SignedOutRedirectUri = settings.PostLogoutUri;

                options.Scope.Clear();
                options.Scope.Add("openid");
                options.Scope.Add("ccms");
                options.Scope.Add("profile");

                options.ClaimActions.Remove("amr");
                options.ClaimActions.Remove("auth_time");
                options.ClaimActions.MapUniqueJsonKey("website", "website");

                options.ClaimActions.Add(new MapAllClaimsAction());

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false
                };

                options.Events = new OpenIdConnectEvents
                {
                    OnRemoteFailure = context =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("/Login");

                        return Task.FromResult(0);
                    },
                };

                options.Events.OnRedirectToIdentityProvider = context =>
                {
                    context.ProtocolMessage.Prompt = "login";
                    return Task.CompletedTask;
                };
            });

        services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");

        services.AddMvc(config =>
        {
            config.EnableEndpointRouting = false;
            var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
            config.Filters.Add(new AuthorizeFilter(policy));
            config.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); //  it validates all of requests, except for GET requests
        }).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

        services.AddAuthorization(options =>
        {
            options.AddPolicy("Permissions", policy =>
            {
                policy.RequireAssertion(context => PermissionGranted(context));
            });
        });
    }

这是配置方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseSession();
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.Use(async (context, next) =>
    {
        context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");

        var tokens = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
            new CookieOptions() { HttpOnly = false });
        await next();
    });

    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Login}/{action=Index}/{id?}");
    });
}

我正在使用 Microsoft.AspNetCore.Authentication.OpenIdConnect -vERSION 3.0.0 进行身份验证和授权的自定义策略。如果我在控制器上使用 [Authorize(Permissions)],这是在用户完全通过身份验证之前获得的方法:

private bool PermissionGranted(AuthorizationHandlerContext context)
{
    var result = false;

    var httpContext = contextAccessor.HttpContext;
    var request = httpContext.Request;
    var requestPath = request.Path.Value.ToLower();
    var method = request.Method.ToLower();
    var relativePath = requestPath;

    var dbContext = new PasswordManagerContext(settings.ConnectionString);
    var userParameters = Helper.GetUserParameters(httpContext, Log.Logger, settings).Result;
    var allUrls = dbContext.PathAccess.ToList();

    var rolePermissions = dbContext.RolePermissions.ToList();
    var user = dbContext.Users.FirstOrDefault(x => x.Ccmsid == userParameters.CcmsId);
    var regexPath = new Regex(@"\d$");
    if (regexPath.IsMatch(relativePath))
    {
        relativePath = Regex.Replace(relativePath, @"[\d-]", string.Empty); 
    }
    var pathAccess = allUrls.FirstOrDefault(x => x.RelativeUrl == relativePath && x.Method == method);
    if (pathAccess != null)
        result = dbContext.RolePermissions.Any(x => x.RoleId == user.RoleId && x.PathAccessId == pathAccess.Id);
    return result;
}

这个授权-身份验证部分在 .net core 2.2 中运行良好 我在配置中做错了吗?任何帮助表示赞赏!

标签: .netasp.net-coreasp.net-core-3.0

解决方案


推荐阅读