我有一个应用程序,它本质上是一个位于 dotnet core 2.1 应用程序中的 Vue.JS SPA,提供 API 服务。当我使用当前的 Startup.cs 配置启动应用程序时,它会启动 3 个窗口。这些窗口中的 1 个是实际的 ASP.Net Core 应用程序根目录 - 其他 2 个(不要问我为什么 2 个)是您在执行时获得的 Vue.js 开发服务器的副本npm run serve
。
我遇到的问题是,虽然如果我使用在第一个窗口中运行的实例,身份验证工作正常,但如果我尝试使用 Vue.JS 服务器窗口登录,那么我只会得到 401。
我的第一个想法是 CORS,所以我设置了一个 CORS 策略,纯粹是为了在开发模式下运行,但这并没有解决问题。在没有 Vue.JS 服务器的情况下进行开发实际上是不可行的,因为没有它我没有 HMR,并且每次进行设计更改时都需要重新加载整个应用程序状态。
我之前已经使用 .net Framework 4.6 API 后端进行了此设置,完全没有问题,所以我只能认为这是一种现代安全增强功能,它阻止了我需要配置为在开发中关闭的代理或其他东西。
欢迎任何关于我如何解决这个问题的建议。
这是我当前的 Startup.cs 配置...
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,
ApplicationDbContext context, RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager)
{
if (env.IsDevelopment())
{
app
.UseDeveloperExceptionPage()
.UseDatabaseErrorPage()
.UseCors("DevelopmentPolicy");
}
else
{
app
.UseExceptionHandler("/Home/Error")
.UseHsts();
}
app
.UseAuthentication()
.UseHttpsRedirection()
.UseStaticFiles()
.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "VueApp";
if (env.IsDevelopment())
{
spa.UseVueCliServer("serve");
}
});
DbInitializer.Initialize(context, roleManager, userManager, env, loggerFactory);
}
...和配置服务...
public void ConfigureServices(IServiceCollection services)
{
services
.AddLogging(builder => builder
.AddConsole()
.AddDebug());
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
services
.AddCors(options =>
{
options.AddPolicy("DevelopmentPolicy",
policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
// In production, the Vue files will be served from this directory
services.AddSpaStaticFiles(configuration => { configuration.RootPath = "wwwroot"; });
services.AddAuthentication();
services
.ConfigureEntityFramework(Configuration)
.ConfigureEntityServices()
.ConfigureIdentityDependencies()
.ConfigureDomainServices()
.ConfigureApplicationCookie(config =>
{
config.SlidingExpiration = true;
config.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = cxt =>
{
cxt.Response.StatusCode = 401;
return Task.CompletedTask;
},
OnRedirectToAccessDenied = cxt =>
{
cxt.Response.StatusCode = 403;
return Task.CompletedTask;
},
OnRedirectToLogout = cxt => Task.CompletedTask
};
});
}
...并且身份在这里与 EF 配置混为一谈...
public static IServiceCollection ConfigureEntityFramework(this IServiceCollection services, string connectionString)
{
services
.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString))
.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = true;
})
.AddRoleManager<RoleManager<IdentityRole>>()
.AddSignInManager<SignInManager<ApplicationUser>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
return services;
}
我的 vue.config.js 看起来像这样......
const baseUrl = ''
module.exports = {
publicPath: baseUrl + '/',
// place our built files into the parent project where they will be copied
// into the distribution for deployment
outputDir: '../wwwroot',
filenameHashing: true, //process.env.NODE_ENV === 'production',
lintOnSave: 'error',
css: {
modules: false,
sourceMap: process.env.NODE_ENV !== 'production',
loaderOptions: {
sass: {
data: `
$fa-font-path: ${process.env.NODE_ENV !== 'production' ? '"~/fonts"' : '"' + baseUrl + '/fonts"'};
@import "@/scss/base/index.scss";
@import "@/scss/helpers/index.scss";
`
}
}
},
devServer: {
host: 'localhost',
port: 8080,
hot: true,
open: true,
openPage: '',
overlay: true,
disableHostCheck: true,
proxy: {
// Proxy services to a backend API
'/api': {
target: process.env.PROXY || 'https://localhost:44368',
secure: false,
changeOrigin: true
}
}
},
// these node_modules use es6 so need transpiling for IE
transpileDependencies: [
]
}