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 本身负责。
让我知道你怎样去!
推荐阅读
- angular - 在没有服务Angular的ngOnInit中创建一个函数
- unified-service-desk - Unified Service Desk 单一登录选项
- powerquery - 电源查询 - 具有动态列数的 List.NonNullCount
- java - 动态报告导出pdf类未找到异常错误
- python - 如何获取来自数组的选定数字的坐标
- php - 递归数组列表类别
- c - C 代码只能在一个项目中工作,不能在任何新项目中工作(不会写 txt 文件)
- javascript - 在 JavaScript 中创建对象数组的所有组合
- swift - 更改 ViewController 后计数器重置为零
- c# - C# SerialPort.Write()方法的误解