我正试图在我的ASP.NET Core 2.0项目中使用Identity实现身份验证,但它似乎不起作用。我实现Identity的最后一个项目是ASP.NET MVC 5项目,现在情况发生了很大变化。我跳过了Core 1.0和1.1,所以我不知道在这些情况下是如何完成的,尽管从我读到的内容来看,它应该基本相似。
不过我不能让它为我工作。当我说它不起作用时,我的意思是,即使我没有被授权,我也不会被重定向到登录页面。
我所做的唯一定制是实现我自己的用户存储和我自己的扩展,以在不需要角色的情况下添加身份,因为我不会使用角色。我可以对我搞砸的事情给出一些指导,因为从我的角度来看,现在一切都太复杂了。这是我目前掌握的代码:
启动.cs
public void ConfigureServices(
IServiceCollection services) {
services.AddDbContext<CustomDbContext>();
services.AddTransient<IUserStore<GlobalUser>, CustomUserStore<GlobalUser>>();
services.AddIdentity<GlobalUser>();
services.AddMvc();
}
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc();
}
ServiceCollectionExtensions.cs
我只是查看了内置AddIdentity<TUser, TRole>
的源代码,并省略了与角色相关的内容,所以这里不应该有问题,尽管可能。。。
public static class ServiceCollectionExtensions {
public static IdentityBuilder AddIdentity<TUser>(
this IServiceCollection services,
Action<IdentityOptions> optionsAction = null)
where TUser : class {
services.AddAuthentication(
o => {
o.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
o.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ApplicationScheme;
}).AddCookie(
o => {
o.LoginPath = new PathString("/Login");
o.Events = new CookieAuthenticationEvents {
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
};
});
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
services.TryAddScoped<IdentityErrorDescriber>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser>>();
services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();
if (optionsAction != null) {
services.Configure(optionsAction);
}
return new IdentityBuilder(typeof(TUser), services);
}
}
我想我必须像MVC 5中那样添加Authorize过滤器,但我似乎无法在全局范围内做到这一点。当我将其应用于默认控制器时,我会得到以下异常:
未指定身份验证方案,也没有找到DefaultChallengeScheme。
但我以为我在自定义AddIdentity
方法中设置方案?我需要一些指导,我很感激任何人送我去。
我想明白了,是我在制作自己的AddIdentity
扩展时忽略了一些东西。在传递选项之前,我应该将IdentityConstants.ApplicationScheme
作为参数传递给AddCookie
。我仔细检查了身份来源,发现我没有找到。我一添加它,一切都正常了。因此:
// ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ this is what was missing
}).AddCookie(IdentityConstants.ApplicationScheme,
o => {
这最终是我自己造成的问题。。。
我和你遇到了同样的问题。我不得不实现基于FormsAuthentication
cookie的自定义身份验证,这在.net核心中不存在,我们有一些使用FormsAuthentication
的ASP.net系统,我们需要互操作。我解决这个问题的方法是先将AuthorizeFilter
划分为子类,然后再将override
划分为OnAuthorizationAsync(AuthorizationFilterContext context)
。这就是我用的:
public class AuthFilter : AuthorizeFilter
{
public override Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (context.Filters.Any(item => item is IAsyncAuthorizationFilter && item != this || item is IAllowAnonymousFilter))
{
return Task.FromResult(0);
}
if (!context.HttpContext.User.Identity.IsAuthenticated)
{
context.Result = new UnauthorizedResult();
return Task.FromResult(0);
}
return base.OnAuthorizationAsync(context);
}
}
然后你必须在ConfigureServices
的Startup.cs
中注册,即
services.AddMvc(options =>
{
options.Filters.Add(new AuthFilter(
new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build()));
});
这将是默认情况,使您的所有控制器都需要授权。如果您需要匿名登录,请将[AllowAnonymous]
添加到您的控制器