部署在GoDaddy的ASP.NET Core 6应用认证/会话超时问题求助
ASP.NET Core 6 部署GoDaddy后认证/会话超时问题求助
我基于ASP.NET Core 6开发的应用在本地运行完全正常,但部署到GoDaddy服务器环境后,未授权用户尝试访问部分功能时会出现认证或会话超时问题。已进行大量排查仍无法定位根因,请求技术协助。
应用Program.cs代码
using Portal._keenthemes.libs; using Portal._keenthemes; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Portal.Data; using PortalServices.Context; using PortalServices.Models; using PortalServices.Interfaces; using Microsoft.AspNetCore.Localization; using System.Globalization; using Portal.Security; using PortalServices.Services; using Portal.Data.Data; using PortalServices.Models.Email; using Portal.GlobalValues; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Options; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity<User>( options => options.SignIn.RequireConfirmedAccount = true ) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddTokenProvider<EmailConfirmationTokenProvider<User>>("email_confirmation_provider"); builder.Services.AddDbContext<PortalContext>(options => options.UseSqlServer(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.ConfigureApplicationCookie(options => { options.LoginPath = "/Account/Login"; options.ExpireTimeSpan = TimeSpan.FromDays(365); options.SlidingExpiration = false; }); builder.Services.Configure<SecurityStampValidatorOptions>(o => o.ValidationInterval = TimeSpan.FromHours(7)); builder.Services.AddScoped<IKTTheme, KTTheme>(); builder.Services.AddSingleton<IKTBootstrapBase, KTBootstrapBase>(); builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); builder.Services.AddControllersWithViews() .AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix) .AddDataAnnotationsLocalization(); builder.Services.Configure<RequestLocalizationOptions>(options => { options.DefaultRequestCulture = new RequestCulture("en-NZ"); options.SupportedCultures = new List<CultureInfo> { new CultureInfo("en-NZ") }; options.RequestCultureProviders = new List<IRequestCultureProvider>(); }); builder.Services.Configure<IdentityOptions>(options => { options.Password.RequireDigit = true; options.Password.RequiredLength = 6; options.Password.RequireNonAlphanumeric = false; options.SignIn.RequireConfirmedAccount = false; options.User.RequireUniqueEmail = true; }); builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromHours(15); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); builder.Services.AddAuthorization(options => { options.AddPolicy("Admin", policy => { policy.AddRequirements(new AdminRole()); policy.RequireAuthenticatedUser(); }); }); IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.Configure<SmtpSettings>(configuration.GetSection("SmtpSettings")); builder.Services.AddScoped<IPortalContext, PortalContext>(); builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<ICategoriesService, CategoriesService>(); builder.Services.AddScoped<IProductService, ProductService>(); builder.Services.AddScoped<IEmailService, EmailService>(); builder.Services.AddScoped<IJobService, JobService>(); builder.Services.AddHostedService<ScheduledService>(); var app = builder.Build(); KTThemeSettings.init(configuration); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios app.UseHsts(); } app.UseSession(); app.UseRequestLocalization(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseThemeMiddleware(); app.MapControllerRoute( name: "Identity", pattern: "{area:exists}/{controller=Identity}/{action=Logout}"); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "Admin", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}", defaults: new { area = "Admin" } ); endpoints.MapGet("/", async context => { if (context.User.Identity.IsAuthenticated) { var userManager = context.RequestServices.GetRequiredService<UserManager<User>>(); var user = await userManager.GetUserAsync(context.User); if(user == null) { context.Response.Redirect("/Account/Login"); } else if (await userManager.IsInRoleAsync(user, "Admin")) { context.Response.Redirect("/Admin"); return; } else if (await userManager.IsInRoleAsync(user, "Seller")) { context.Response.Redirect("/Seller"); return; } else if (await userManager.IsInRoleAsync(user, "Freelancer")) { context.Response.Redirect("/Freelancer"); return; } } context.Response.Redirect("/Home/Index"); }); }); app.MapRazorPages(); using (var scope = app.Services.CreateScope()) { await DbSeeder.SeedRoleAndAdminAsync(scope.ServiceProvider); } app.Run(); public class EmailConfirmationTokenProvider<TUser> : DataProtectorTokenProvider<TUser> where TUser : class { public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider, IOptions<EmailConfirmationTokenProviderOptions> options, ILogger<EmailConfirmationTokenProvider<TUser>> logger) : base(dataProtectionProvider, options, logger) { } } public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions { }
排查方向及解决方案建议
会话存储优化:当前使用
AddDistributedMemoryCache(),GoDaddy共享宿主环境下应用进程可能被频繁回收,导致内存缓存丢失。建议改用SQL Server分布式缓存:builder.Services.AddDistributedSqlServerCache(options => { options.ConnectionString = connectionString; options.SchemaName = "dbo"; options.TableName = "SessionCache"; });执行对应的数据库迁移脚本创建SessionCache表。
Cookie配置修正:生产环境需确保Cookie安全属性正确,适配GoDaddy代理环境:
builder.Services.ConfigureApplicationCookie(options => { options.LoginPath = "/Account/Login"; options.ExpireTimeSpan = TimeSpan.FromDays(365); options.SlidingExpiration = false; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.SameSite = SameSiteMode.Lax; // 若使用子域名,添加:options.Cookie.Domain = ".yourdomain.com"; }); builder.Services.Configure<SessionOptions>(options => { options.IdleTimeout = TimeSpan.FromHours(15); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.SameSite = SameSiteMode.Lax; });数据保护密钥持久化:ASP.NET Core数据保护密钥默认存储在本地,应用重启后密钥丢失会导致Cookie验证失败。配置密钥持久化到GoDaddy允许的目录:
builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"D:\home\site\wwwroot\App_Data\Keys")) .SetApplicationName("YourApplicationName");确保该目录有读写权限。
反向代理头部信任:GoDaddy使用反向代理,需配置应用信任转发的头部,避免HTTPS重定向或认证错误:
builder.Services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // 添加GoDaddy代理IP到已知代理列表,可从GoDaddy文档获取 options.KnownProxies.Add(IPAddress.Parse("xxx.xxx.xxx.xxx")); });在中间件管道最前面添加:
app.UseForwardedHeaders();中间件顺序调整:Session中间件需在Routing和Authentication之前,调整管道顺序为:
app.UseForwardedHeaders(); app.UseHsts(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseSession(); app.UseRequestLocalization(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization();应用池回收配置:登录GoDaddy控制面板,调整应用池回收规则:
- 取消固定时间回收,改为按需回收
- 提高内存/CPU回收阈值
- 设置回收时间为非业务高峰时段
启用详细日志:修改appsettings.json的Logging配置,记录认证和Session相关日志:
"Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore.Authentication": "Debug", "Microsoft.AspNetCore.Session": "Debug", "Microsoft.AspNetCore.DataProtection": "Debug" } }查看GoDaddy日志目录(
D:\home\LogFiles\http\RawLogs)中的错误信息,定位具体问题。
内容的提问来源于stack exchange,提问作者Rashid Zafar Iqbal
相关产品推荐
相关产品推荐

