.net core Angular SPA:如果“启动”页面中定义的策略不成功,则重定向到错误页面

时间:2019-06-25 21:47:27

标签: c# angular asp.net-core .net-core javascriptservices

我在Visual Studio中使用最新的SPA模板。没有视图文件夹和 index.cshtml 文件。

index.html 文件,该文件位于带有 标签的angular客户应用文件夹下。

页面文件夹下也有 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 :(得分:0)

尽管页面和视图文件共享相同的.cshtml文件扩展名,但页面与普通视图文件有很大不同。请注意/Pages/Error.cshtml(以及相关的Error.cshtml.cs)是一个page,它将被编译成MVC操作。换句话说,它直接处理请求。页面实际上不是控制器使用的视图文件。

对于您的问题,最简单的方法是如下更改代码:

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

或者,如果您想使用AccessDenied操作,也可以如下更改此操作:

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

答案 1 :(得分:0)

您应该将代码更改为此

 [AllowAnonymous]
 public IActionResult AccessDenied()
 {
    return RedirectToPage("/Error");
 }