Jon*_*Jon 34 asp.net identity claims-based-identity asp.net-mvc-5 asp.net-identity
我正在尝试为MVC5站点设置OAuth(在VS2012中).
我正在使用Fluent NHibernate.我已经设置了自己的Userstore并传入一个存储库对象来访问NHibernate会话对象.我将我的商店传递给默认的aspnet usermanager提供程序.这最终适用于本地注册和登录.我不是要设置连接/注册Facebook.
它获得了一个成功的帐户.在用户表中添加用户,在登录表中添加记录然后爆炸.我没有在用户存储中实现声明,或者在用户对象中放置声明集合.(不确定这是否真的需要,我正在剥离所有可能出错的东西以找到问题的根源).
爆炸的线是(在账户控制器中):
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
Run Code Online (Sandbox Code Playgroud)
在这种方法中:
private async Task SignInAsync(IdentityUser user, bool isPersistent)
Run Code Online (Sandbox Code Playgroud)
这是堆栈跟踪的结束
[ArgumentNullException: Value cannot be null.
Parameter name: value]
System.Security.Claims.Claim..ctor(String type, String value, String valueType, String issuer, String originalIssuer, ClaimsIdentity subject, String propertyKey, String propertyValue) +14108789
System.Security.Claims.Claim..ctor(String type, String value, String valueType) +62
Microsoft.AspNet.Identity.<CreateAsync>d__0.MoveNext() +481
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +144
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +84
System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +49
Web.Controllers.<SignInAsync>d__42.MoveNext() in d:\Google Drive\Development\GoalManagement\Web\Controllers\AccountController.cs:375
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +144
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +84
Web.Controllers.<ExternalLoginConfirmation>d__35.MoveNext() in d:\Google Drive\Development\GoalManagement\Web\Controllers\AccountController.cs:311
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +144
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +84
public class IdentityUser : IUser
{
public IdentityUser()
{
Logins = new List<IdentityUserLogin>();
}
public string Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public IList<IdentityUserLogin> Logins { get; set; }
}
public class IdentityUserLogin
{
public string LoginProvider { get; set; }
public string ProviderKey { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果需要,我可以包含我的用户代码:我没有把它放入,因为它是一个大文件,可能会减少问题.
我不确定为什么它甚至试图创建索赔对象以及为什么它会爆炸.因为我只有VS2012,所以我一直在网上的例子中修补它们.
正如@Shoe所建议我继承自UserManager:
public class NHibernateAspnetUserManager<TUser> : UserManager<TUser> where TUser : IdentityUser
{
public NHibernateAspnetUserManager(IUserStore<TUser> store) : base(store)
{
}
public override Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType)
{
ClaimsIdentity identity = new ClaimsIdentity();
return Task.FromResult(identity);
}
}
Run Code Online (Sandbox Code Playgroud)
它现在不再抛出错误,但实际上并没有验证我多少次使用Facebook注册/登录.
总结一下.有了@ Shoe的信息,我试图重写UserManager.CreateIdentityAsync:
public override Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType)
{
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
return Task.FromResult(identity);
}
Run Code Online (Sandbox Code Playgroud)
并尝试使用返回的默认值(空列表)实现IUserClaimStore.
第一个不会通过错误但不会最终验证.后者仍将通过奇怪的声明"System.Security.Claims.Claim..ctor"错误
编辑
找出ctor错误发生的原因.用户对象返回时没有ID,因此默认情况下UserManager感到不安.修复了并使用了UserManager现在不再抛出错误的默认值,但仍然没有记录用户.它返回的身份对象看起来很好.
Pat*_*ins 80
我在过去遇到了同样的错误,但只有在我使用Entity Framework Migration Tool创建用户时才会出错.在创建用户并使用网站签名时,我没有错误.
我的错误是我没有向SecurityStamp提供迁移.
SecurityStamp = Guid.NewGuid().ToString()
Run Code Online (Sandbox Code Playgroud)
这个属性设置,一切正常.
小智 13
我遇到了类似的问题.解决方案是设置User-Entity的SecurityStamp-Property.
背景:客户希望在数据库中拥有带密码的Admin-/Superuser-Accounts,以及一组其他用户 - 他们应该能够在没有密码的情况下登录 - 在XML文件中......
所以我从Entity Framework UserStore继承,覆盖FindByIdAsync和FindByNameAsync,为用户搜索XML文件并返回一个新的User-Entity.(如果默认实现没有找到用户)
在创建ClaimsIdentity时,我和Jon有相同的例外.
经过一番挖掘后,我发现我新创建的User-Entities没有SecurityStamp.而asp.net默认的UserManager需要一个SecurityStamp,并希望在ClaimsIdentity中将其设置为一个Claim.
在为该属性设置值后 - 我使用了包含前缀和用户名的字符串 - 一切都适合我.
当密码少于 6 个字符时,我遇到了这个问题。任何比这更大的东西我都不会收到这个错误。
6 个字符是其最小默认设置。
当然你可以改变这种行为。
services.Configure<IdentityOptions>(options =>
{
options.Password.RequiredLength = 6;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequireDigit = false;
options.Password.RequireNonAlphanumeric = false;
});
Run Code Online (Sandbox Code Playgroud)
默认情况下,UserManager即使您尚未实现声明,也会尝试获取声明并添加/删除声明。如果您不需要声明,我找到的解决方案是UserManager在您的UserStore.
public Task AddClaimAsync(TUser user, Claim claim)
{
return Task.FromResult<int>(0);
}
public Task<IList<Claim>> GetClaimsAsync(TUser user)
{
return Task.FromResult<IList<Claim>>(new List<Claim>());
}
public Task RemoveClaimAsync(TUser user, Claim claim)
{
return Task.FromResult<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20970 次 |
| 最近记录: |