Asp.net-Core-2.2
防止在 asp.net core 2.2 中重定向到 /Account/Login
/Account/Login當使用者未登錄時,我試圖阻止應用程序重定向到asp.net core 2.2。即使我寫
LoginPath = new PathString("/api/contests");了任何未經授權的請求仍然被重定向到/Account/Login這是我的 Startup.cs:
using System; using System.Reflection; using AutoMapper; using Contest.Models; using Contest.Tokens; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Swashbuckle.AspNetCore.Swagger; namespace Contest { public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAutoMapper(); // In production, the React files will be served from this directory services.AddSpaStaticFiles(configuration => { configuration.RootPath = "clientapp/build"; }); // ===== Add our DbContext ======== string connection = Configuration.GetConnectionString("DBLocalConnection"); string migrationAssemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; services.AddDbContext<ContestContext>(options => options.UseSqlServer(connection, sql => sql.MigrationsAssembly(migrationAssemblyName))); // ===== Add Identity ======== services.AddIdentity<User, IdentityRole>(o => { o.User.RequireUniqueEmail = true; o.Tokens.EmailConfirmationTokenProvider = "EMAILCONF"; // I want to be able to resend an `Email` confirmation email // o.SignIn.RequireConfirmedEmail = true; }).AddRoles<IdentityRole>() .AddEntityFrameworkStores<ContestContext>() .AddTokenProvider<EmailConfirmationTokenProvider<User>("EMAILCONF") .AddDefaultTokenProviders(); services.Configure<DataProtectionTokenProviderOptions>(o => o.TokenLifespan = TimeSpan.FromHours(3) ); services.Configure<EmailConfirmationTokenProviderOptions>(o => o.TokenLifespan = TimeSpan.FromDays(2) ); // ===== Add Authentication ======== services.AddAuthentication(o => o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = "auth_cookie"; options.Cookie.SameSite = SameSiteMode.None; options.LoginPath = new PathString("/api/contests"); options.AccessDeniedPath = new PathString("/api/contests"); options.Events = new CookieAuthenticationEvents { OnRedirectToLogin = context => { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return Task.CompletedTask; }, }; }); // ===== Add Authorization ======== services.AddAuthorization(o => { }); services.AddCors(); // ===== Add MVC ======== services.AddMvc(config => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); config.Filters.Add(new AuthorizeFilter(policy)); }) .AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // ===== Add Swagger ======== services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Title = "Core API", Description = "Documentation", }); var xmlPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}Contest.xml"; c.IncludeXmlComments(xmlPath); }); } // 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("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseSpaStaticFiles(new StaticFileOptions() { }); app.UseCors(policy => { policy.AllowAnyHeader(); policy.AllowAnyMethod(); policy.AllowAnyOrigin(); policy.AllowCredentials(); }); app.UseAuthentication(); app.UseMvc(); if (env.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core API"); }); } app.UseSpa(spa => { spa.Options.SourcePath = "clientapp"; if (env.IsDevelopment()) { // spa.UseReactDevelopmentServer(npmScript: "start"); spa.UseProxyToSpaDevelopmentServer("http://localhost:3000"); } }); } } }我設法通過創建一個控制器來處理這條路線來繞過這個:
[Route("/")] [ApiController] public class UnauthorizedController : ControllerBase { public UnauthorizedController() { } [HttpGet("/Account/Login")] [AllowAnonymous] public IActionResult Login() { HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; return new ObjectResult(new { StatusCode = StatusCodes.Status401Unauthorized, Message = "Unauthorized", }); } }我的設置有什麼問題?謝謝
你好,歡迎來到 StackOverflow 👋
您遇到的行為與您使用 ASP.NET Identity 的事實有關。當您呼叫 時
services.AddIdentity,會在後台註冊一個基於 cookie 的身份驗證方案並將其設置為預設質詢方案,如您在 GitHub 上的程式碼中所見。即使您自己註冊了一個 cookie 身份驗證方案並將其設置為預設方案,但特定的預設方案(如
AuthenticateScheme、ChallengeScheme、SignInScheme等)優先。DefaultScheme僅當未設置特定時才由身份驗證系統使用。要回答您的問題,您可以使用輔助方法將配置設置應用於 ASP.NET 身份 cookie 選項
services.ConfigureApplicationCookie,如下所示:// ===== Add Identity ======== services.AddIdentity<User, IdentityRole>(o => { o.User.RequireUniqueEmail = true; o.Tokens.EmailConfirmationTokenProvider = "EMAILCONF"; // I want to be able to resend an `Email` confirmation email // o.SignIn.RequireConfirmedEmail = true; }).AddRoles<IdentityRole>() .AddEntityFrameworkStores<ContestContext>() .AddTokenProvider<EmailConfirmationTokenProvider<User>("EMAILCONF") .AddDefaultTokenProviders(); services.Configure<DataProtectionTokenProviderOptions>(o => o.TokenLifespan = TimeSpan.FromHours(3) ); services.Configure<EmailConfirmationTokenProviderOptions>(o => o.TokenLifespan = TimeSpan.FromDays(2) ); // ===== Configure Identity ======= service.ConfigureApplicationCookie(options => { options.Cookie.Name = "auth_cookie"; options.Cookie.SameSite = SameSiteMode.None; options.LoginPath = new PathString("/api/contests"); options.AccessDeniedPath = new PathString("/api/contests"); // Not creating a new object since ASP.NET Identity has created // one already and hooked to the OnValidatePrincipal event. // See https://github.com/aspnet/AspNetCore/blob/5a64688d8e192cacffda9440e8725c1ed41a30cf/src/Identity/src/Identity/IdentityServiceCollectionExtensions.cs#L56 options.Events.OnRedirectToLogin = context => { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return Task.CompletedTask; }; });這也意味著您可以安全地刪除添加基於 cookie 的身份驗證方案的部分,因為這由 ASP.NET Identity 本身負責。
讓我知道你怎樣去!