Dan*_*iel 20 c# .net-core asp.net-core angular
我正在使用dotnet core 2.1中的角度SPA应用程序的"新"项目模板,如文章中所述使用Angular项目模板和ASP.NET Core.
但是这篇文章没有提到保护SPA本身的任何内容.我找到的所有信息都是关于保护WEBAPI,但首先我对保护SPA感兴趣.
这意味着:当我打开我的SPA时,例如https:// localhost:44329 /我希望立即重定向到授权服务器,而不是单击某个将执行身份验证的按钮.
背景:
当前的方法是实施需要经过身份验证的用户的MVC策略.但这只能应用于MVC控制器.这就是我添加HomeController以满足第一个请求的原因.
见项目结构:
我的Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "CustomScheme";
})
.AddCookie()
.AddOAuth("CustomScheme", options =>
{
// Removed for brevity
});
services.AddMvc(config =>
{
// Require a authenticated user
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseAuthentication();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
Run Code Online (Sandbox Code Playgroud)
当前行为:当我启动我的SPA时,由于MVC策略,我立即被重定向到我的授权服务器.验证成功后,我看到家庭控制器的索引方法,但不是我的SPA.
所以问题是我从认证服务器重定向后应该如何服务我的SPA?
Geo*_*ros 16
我有一些似乎有用的东西.
在我的研究中,我发现这篇文章建议使用中间件而不是Authorize属性.
现在,在post autService中使用的方法在我的情况下似乎不起作用(不知道为什么,我将继续调查并发布我后来发现的whaterver).
所以我决定采用更简单的解决方案.这是我的配置
app.Use(async (context, next) =>
{
if (!context.User.Identity.IsAuthenticated)
{
await context.ChallengeAsync("oidc");
}
else
{
await next();
}
});
Run Code Online (Sandbox Code Playgroud)
在这种情况下,oidc在Spa应用程序之前启动并且流程正常工作.根本不需要控制器.
HTH
使用@George的中间件将要求对所有请求进行身份验证。如果只想对本地主机运行此命令,请将其添加到包装在env.IsDevelopment()块中的UseSpa下。
对于已部署的环境也很有效的另一个选项是从spa备用路由中返回index.html。
启动:
if (!env.IsDevelopment())
{
builder.UseMvc(routes =>
{
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "AuthorizedSpaFallBack" });
});
}
Run Code Online (Sandbox Code Playgroud)
家用控制器:
[Authorize]
public IActionResult AuthorizedSpaFallBack()
{
var file = _env.ContentRootFileProvider.GetFileInfo("ClientApp/dist/index.html");
return PhysicalFile(file.PhysicalPath, "text/html");
}
Run Code Online (Sandbox Code Playgroud)
如果您需要base.href来匹配浏览器请求url(例如,具有Path值的cookie),则可以使用正则表达式对其进行模板化(或像其他示例一样使用razer视图)。
[Authorize]
public IActionResult SpaFallback()
{
var fileInfo = _env.ContentRootFileProvider.GetFileInfo("ClientApp/dist/index.html");
using (var reader = new StreamReader(fileInfo.CreateReadStream()))
{
var fileContent = reader.ReadToEnd();
var basePath = !string.IsNullOrWhiteSpace(Url.Content("~")) ? Url.Content("~") + "/" : "/";
//Note: basePath needs to match request path, because cookie.path is case sensitive
fileContent = Regex.Replace(fileContent, "<base.*", $"<base href=\"{basePath}\">");
return Content(fileContent, "text/html");
}
}
Run Code Online (Sandbox Code Playgroud)
基于 Georges Legros,我设法使用 Identity Server 4(开箱即用的 VS 项目)使其适用于 .Net Core 3,以便在用户未通过身份验证时不会命中 app.UseSpa 管道首先通过身份服务器。这更好,因为您不必等待 SPA 加载然后重定向到登录。
您必须确保授权/角色正常工作,否则 User.Identity.IsAuthenticated 将始终为假。
public void ConfigureServices(IServiceCollection services)
{
...
//Change the following pre-fab lines from
//services.AddDefaultIdentity<ApplicationUser>()
// .AddEntityFrameworkStores<ApplicationDbContext>();
//To
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddRoles<IdentityRole>()
//You might not need the following two settings
.AddDefaultUI()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
...
}
Run Code Online (Sandbox Code Playgroud)
然后添加如下设置如下管道:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
//Added this to redirect to Identity Server auth prior to loading SPA
app.Use(async (context, next) =>
{
if (!context.User.Identity.IsAuthenticated)
{
await context.ChallengeAsync("Identity.Application");
}
else
{
await next();
}
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4395 次 |
| 最近记录: |