.net core Angular SPA: перенаправление на страницу ошибки, если политика, определенная на странице запуска, не выполнена - PullRequest
0 голосов
/ 26 июня 2019

Я использую последний шаблон SPA в Visual Studio.Которые не имеют папки views и index.cshtml file.Файл index.html находится в папке углового клиентского приложения с тегом .Также в папке pages есть файл Error.cshtml .Итак, структура выглядит так:enter image description here

Итак, в обработчике политики я написал следующий код для перенаправления:

 protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, Requirement requirement)
    {
        if (context.User.HasClaim(ClaimTypes.Role, Roles.Admin))
        {
            context.Succeed(requirement);
        }
        else
        {
            var authFilterContext = context.Resource as AuthorizationFilterContext;
            authFilterContext.Result = new RedirectToActionResult("AccessDenied", "Account", null);
        }


        return Task.FromResult(0);
    }

А в контроллере учетной записи у меня есть следующие действия:

 [AllowAnonymous]
    public IActionResult AccessDenied()
    {
      return this.View("/Pages/Error");
    }

Но действие завершается ошибкой, сообщая, что представление об ошибке не найдено.

Startup.cs

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });

        services.Configure<FormOptions>(x =>
        {
            x.ValueLengthLimit = int.MaxValue;
            x.MultipartBodyLengthLimit = int.MaxValue;
            x.MultipartHeadersLengthLimit = int.MaxValue;
        });

        services.AddApplicationInsightsTelemetry(this.Configuration);
        services.AddSingleton<ITelemetryInitializer, AppInsightsInitializer>();

        // Adds services required for using options.
        services.AddOptions();

        services.Configure<AppSettingsConfig>(this.Configuration.GetSection("AppSettings"));




        var azureAdConfig = new AzureAdConfig();


        if (this.RequireAAD())
        {
            // Add framework services.
            services.Configure<MvcOptions>(options =>
            {
                options.Filters.Add(new RequireHttpsAttribute());
            });
        }
        else
        {
            services.Configure<MvcOptions>(options =>
            {
            });
        }

        // Add Authentication services.
        if (this.RequireAAD())
        {
            // Configure the OWIN pipeline to use cookie auth.
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie()

            .AddOpenIdConnect(options =>
            {
                options.ClientId = azureAdConfig.ClientId;
                options.ClientSecret = azureAdConfig.ClientSecret;
                options.Authority = string.Format(azureAdConfig.AADInstance, azureAdConfig.Tenant);
                options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                options.Resource = azureAdConfig.ResourceURI_Graph;
                // PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"],
                options.Events = new AuthEvents(azureAdConfig, connectionStringsConfig);
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());

                options.AddPolicy(
                    PolicyNames.Require,
                    policy =>
                    {
                        policy.AddRequirements(new Requirement(this.Configuration.GetValue<bool>("AppSettings:Enable")));
                        policy.RequireAuthenticatedUser();
                        policy.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);
                    });
            });
        }

        this.ConfigureStore(services);

        if (this.RequireAAD())
        {
            services.AddMvc(config =>
            {
                var policy = new AuthorizationPolicyBuilder()
                                 .RequireAuthenticatedUser()
                                 .Build();
                config.Filters.Add(new Microsoft​.AspNetCore​.Mvc​.Authorization.AuthorizeFilter(policy));
                config.Filters.Add(new Microsoft​.AspNetCore​.Mvc​.Authorization.AuthorizeFilter(PolicyNames.Require));
                config.Filters.Add(typeof(ExceptionFilter));
            });
        }
        else
        {
            services.AddMvc();
        }
        services.AddAutoMapper();
        // For accessing appinsights for dependency injection?
        services.AddApplicationInsightsTelemetry();
    }

    public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, ILoggerFactory loggerFactory, TelemetryClient tc, IAntiforgery antiforgery)
    {
        var azureAdConfig = new AzureAdConfig();
        this.Configuration.GetSection("Authentication:AzureAd").Bind(azureAdConfig);
        this.SetupStore(app);

        app.UseRewriter(new RewriteOptions().AddRedirectToHttps());

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        // TODO . Switch
        app.UseHttpsRedirection();
        app.UseAuthentication();
        app.UseStaticFiles();
        app.UseMiddleware(typeof(ErrorHandlingMiddleware));

       app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
            routes.MapRoute(
              name: "static",
              template: "");
        });

        app.UseProtectFolder(new ProtectFolderOptions
        {
            Path = "/Clientapp",
            PolicyName = "Authenticated"
        });

        app.UseSpaStaticFiles();
        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.Options.StartupTimeout = new TimeSpan(days: 0, hours: 0, minutes: 1, seconds: 30);
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }

Ответы [ 2 ]

0 голосов
/ 26 июня 2019

Вы должны изменить свой код на это

 [AllowAnonymous]
 public IActionResult AccessDenied()
 {
    return RedirectToPage("/Error");
 }
0 голосов
/ 26 июня 2019

Хотя файлы страниц и просмотра имеют одинаковое расширение .cshtml, страницы сильно отличаются от файлов обычного вида.Помните, что /Pages/Error.cshtml (и связанный Error.cshtml.cs) - это page, который будет скомпилирован в действие MVC.Другими словами, он обрабатывает запросы напрямую.Страницы на самом деле не являются файлами представления, которые используются контроллерами.

Что касается вашего вопроса, самый простой способ - это изменить ваш код следующим образом:

<strike>authFilterContext.Result = new RedirectToActionResult("AccessDenied", "Account", null);</strike>
authFilterContext.Result = <b>new RedirectToPageResult("/Error", "GET", null);</b>

Или, если вы хотите сделатьПри использовании действия AccessDenied вы также можете изменить это действие, как показано ниже:

[AllowAnonymous]
public IActionResult AccessDenied()
{
    <strike>return this.View("/Pages/Error");</strike>
    <b>return new RedirectToPageResult("/Error", "GET", null);</b>
}
...