Как перенаправить на страницу входа в промежуточное ПО в ядре asp. net с помощью ChallengeAsync - PullRequest
0 голосов
/ 04 февраля 2020

Я пытался ограничить доступ к пути /swagger, используя пользовательское промежуточное ПО. Я почти закончил, но у меня есть одна проблема: я не могу заставить его перенаправить на страницу входа в систему https://localhost:44386/Identity/Account/Login, вместо этого он перенаправляет на https://localhost:44386/swagger/Identity/Account/Login?ReturnUrl=https%3A%2F%2Flocalhost%3A44386%2FIdentity%2FAccount%2FLogin, что вызывает localhost redirected you too many times.

Это Startup.cs класс

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MyDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("MyDbContextConnection")));

            services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<MyDbContext>();

            services.AddAuthorization(options =>
            {
                options.AddPolicy("Admin", policy => policy.RequireClaim("SwaggerPermission", "CanExecute"));
            });

            // Set defaut page
            services.AddRazorPages()
                .AddRazorPagesOptions(options =>
                {
                    options.Conventions.AuthorizeAreaFolder("Identity", "/Home");
                    options.Conventions.AddAreaPageRoute("Identity", "/Account/Login", "");
                });

            // Add swagger
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "SolarPeple API", Version = "v1" });
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme. \r\n\r\nEnter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: 'Bearer 12345abcdef'",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    Scheme = "Bearer"
                });

                var oasr = new OpenApiSecurityRequirement();
                oasr.Add(new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    },
                    Scheme = "oauth2",
                    Name = "Bearer",
                    In = ParameterLocation.Header,
                }, new List<string>());

                c.AddSecurityRequirement(oasr);
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();

                // Enable seeding on Dev
                Seeder.Initialize(app.ApplicationServices);
            }

            // Initialize log4net
            loggerFactory.AddLog4Net();

            // Authenticate when hit swagger page
            app.Map("/swagger", branch =>
            {
                branch.UseSwaggerAuthorization("Admin");
            });

            // Initialize swagger
            app.UseSwagger();

            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "My API");
            });

            // Allow http redirection
            app.UseHttpsRedirection();

            // Allow wwwroot static files to be accessed
            app.UseStaticFiles();

            // Allow routing
            app.UseRouting();


            // Enable authentication of pages
            app.UseAuthentication();

            // Enable roles based authentication
            app.UseAuthorization();



            app.UseEndpoints(endpoints =>
            {
                // Automatically map razor pages
                endpoints.MapControllers();
                endpoints.MapRazorPages();
            });
        }
    }

И промежуточные классы

public static class SwaggerAuthorizationExtensions
    {
        public static IApplicationBuilder UseSwaggerAuthorization(this IApplicationBuilder builder, string policyName)
        {
            return builder.UseMiddleware<SwaggerAuthorization>(policyName);
        }
    }

    public class SwaggerAuthorization
    {
        private readonly RequestDelegate _next;
        private readonly string _policyName;

        public SwaggerAuthorization(RequestDelegate next, string policyName)
        {
            _next = next;
            _policyName = policyName;
        }

        public async Task InvokeAsync(HttpContext context, IAuthorizationService authorizationService)
        {
            var authorizeResult = await authorizationService.AuthorizeAsync(context.User, null, _policyName);

            if (!authorizeResult.Succeeded)
            {
                var redirectUrl = UriHelper.BuildAbsolute(context.Request.Scheme, context.Request.Host, "/Identity/Account/Login");

                await context.ChallengeAsync(new AuthenticationProperties
                {
                    RedirectUri = redirectUrl
                });

                return;
            }

            await _next(context);
        }
    }

1 Ответ

1 голос
/ 04 февраля 2020

Поскольку вы используете ASP. NET Core Identity, для вас по умолчанию используется схема аутентификации cook ie. Это также то, откуда приходит /Identity/Account/Login, поскольку именно по этому пути схема аутентификации cook ie перенаправляет вас, когда пользователь не может быть аутентифицирован.

Это также называется аутентификацией challenge и схема аутентификации cook ie также является схемой по умолчанию challenge . Проверка подлинности - это, по сути, то, что происходит, когда личность пользователя подвергается сомнению, и ему предлагается подтвердить подлинность. Для аутентификации на основе идентификации это означает, что они должны войти в систему, используя свои учетные данные Identity.

Таким образом, перенаправление на /Identity/Account/Login является вызовом схемы аутентификации cook ie. Чтобы вызвать это из вашего промежуточного программного обеспечения, вам просто нужно вызвать context.ChallengeAsync().

AuthenticationProperties, который вы передаете методу ChallengeAsync, используется для настройки этой задачи. Передав RedirectUri, вы указываете, куда должна быть перенаправлена ​​структура аутентификации после , когда вызов был завершен; так что, в основном, после того, как пользователь вошел в систему.

Итак, установив RedirectUri в качестве URL-адреса для входа, вы в основном говорите: «Войдите в систему, а затем перенаправьте на страницу входа, где вы снова войдете в систему» .

Вместо этого вы хотите попросить пользователя войти в систему, а затем перенаправить обратно туда, откуда он пришел или куда он на самом деле хотел go пройти. Самый простой способ сделать это - выбрать путь запроса:

await context.ChallengeAsync(new AuthenticationProperties
{
    RedirectUri = context.Request.Path,
});

Обратите внимание, что если вы хотите получить доступ к пользовательской информации в вашем промежуточном программном обеспечении, вам необходимо убедиться, что промежуточное программное обеспечение для аутентификации работает до этого. Таким образом, вам придется переместить вызов UseAuthentication() дальше вверх по конвейеру. В противном случае пользователь всегда не будет аутентифицирован.

...