我在Visual Studio中使用最新的SPA模板。没有视图文件夹和 index.cshtml 文件。
有 index.html 文件,该文件位于带有 标签的angular客户应用文件夹下。
页面文件夹下也有 Error.cshtml 文件。因此结构如下所示:
所以在策略处理程序中,我编写了以下代码进行重定向:
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");
}
});
}
答案 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");
}