我在哪里设置了
services.AddIdentity<AppUser, AppRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<userManage>()
.AddDefaultTokenProviders();
使用AppUser
和AppRole
的地方,但是似乎因此失败。我不断得到
ArgumentNullException:值不能为null。参数名称:System.Security.Claims.Claim..ctor
处声明的类型
之后
Microsoft.AspNetCore.Identity.IdentityUserClaim1.ToClaim()
整个日志位于底部
在引入IdentityUser
和IdentityRole
的扩展名之前,一切都在工作
对于IDS4设置,我有:
services.AddIdentityServer(options => {
options.UserInteraction.LoginUrl = "/Account/Login";
})
.AddSigningCredential(new X509Certificate2(Path.Combine(".", "certs"
, "IdentityServer4Auth.pfx")))
.AddAspNetIdentity<AppUser>()
.AddConfigurationStore(options => {
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connection_string, sql => sql.MigrationsAssembly(migrations_assembly));
})
.AddOperationalStore(options => {
//options.DefaultSchema = "token";
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connection_string, sql => sql.MigrationsAssembly(migrations_assembly));
})
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddJwtBearerClientAuthentication()
.AddProfileService<IdentityProfileService>();
正常,但切换为
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{ })
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddDistributedMemoryCache();
到
services.AddIdentity<AppUser, AppRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<userManage>()
.AddDefaultTokenProviders();
现在就杀死了它。我知道它可以设置AppUser
,AppRole
和userManage
的范围,因为它们在我的许多应用程序中使用的设置都相同,但是一旦与IDS4现在失败了。在工作时,我扩展了IdentityUser
public class ApplicationUser : IdentityUser {}
该工具也可以正常工作,那是我将这两个应用程序混合在一起的时候,所以AppUser
,AppRole
和userManage
都已经坏了。 我将模型放在下方
也要注意,我已经遵循了日志,而在这里杀死我的是数据库中运行的查询正确。当我运行它时,我看不到任何类型值的空值。为了安全起见,我什至在数据库中清除了所有声明区域中的任何空值,例如角色或用户级别。我在导致故障的区域上设置了一个断点,
var signin_result = await _signInManager.PasswordSignInAsync(_user, test, model.RememberMe, false);
当我查看_user时,我看到它具有安全标记,并且所有值都正确填充
这是用户要求的
SELECT [uc].[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId]
FROM [AspNetUserClaims] AS [uc]
WHERE [uc].[UserId] = @__user_Id_0
但是我看不出问题出在哪里,什么都没有返回空值
日志
2018-10-08 13:17:47.164 -07:00 [Information] Entity Framework Core "2.1.4-rtm-31024" initialized '"ApplicationDbContext"' using provider '"Microsoft.EntityFrameworkCore.SqlServer"' with options: "SensitiveDataLoggingEnabled "
2018-10-08 13:17:47.189 -07:00 [Information] Executed DbCommand ("1"ms) [Parameters=["@__user_Id_0='11325643' (Size = 450)"], CommandType='Text', CommandTimeout='30']"
""SELECT [uc].[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId]
FROM [AspNetUserClaims] AS [uc]
WHERE [uc].[UserId] = @__user_Id_0"
2018-10-08 13:17:47.370 -07:00 [Error] An exception occurred in the database while iterating the results of a query for context type '"test.app.Data.ApplicationDbContext"'."
""System.ArgumentNullException: Value cannot be null.
Parameter name: type
at System.Security.Claims.Claim..ctor(String type, String value, String valueType, String issuer, String originalIssuer, ClaimsIdentity subject, String propertyKey, String propertyValue)
at System.Security.Claims.Claim..ctor(String type, String value)
at Microsoft.AspNetCore.Identity.IdentityUserClaim`1.ToClaim()
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.IShaper<TOut>.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)"
System.ArgumentNullException: Value cannot be null.
Parameter name: type
at System.Security.Claims.Claim..ctor(String type, String value, String valueType, String issuer, String originalIssuer, ClaimsIdentity subject, String propertyKey, String propertyValue)
at System.Security.Claims.Claim..ctor(String type, String value)
at Microsoft.AspNetCore.Identity.IdentityUserClaim`1.ToClaim()
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper`3.Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.IShaper<TOut>.Shape(QueryContext queryContext, ValueBuffer& valueBuffer)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
2018-10-08 13:17:48.680 -07:00 [Information] Executed action "WSU.Sso.Controllers.AccountController.Login (test.app)" in 2022.4589ms
模型,并进行设置(请注意,在无IDS4应用程序中,它们工作正常)
public class AppUser : IdentityUser {}
public class AppRole : IdentityRole {}
public class AppUserClaim : IdentityUserClaim<string> {}
public class AppUserRole : IdentityUserRole<string> {}
public class AppRoleClaims : IdentityRoleClaim<string> {}
public partial class CoreDbContext : IdentityDbContext
<
AppUser, // TUser
AppRole, // TRole
string, // TKey
AppUserClaim, // TUserClaim
AppUserRole, // TUserRole,
IdentityUserLogin<string>, // TUserLogin
AppRoleClaims, // TRoleClaim
IdentityUserToken<string> // TUserToken
>//, ICoreDbContext
{
//etc..
}
我认为问题出在https://github.com/IdentityServer/IdentityServer4.AspNetIdentity/blob/dev/src/UserClaimsFactory.cs,其中UserManager<TUser> userManager
必须为userManage
,因为我对此进行了扩展。我猜我需要扮演我自己的角色吗?
结果是,在移除userManage
并扩展了UserManager<TUser>
之后,仍然失败
System.Security.Claims.Claim..ctor(字符串类型,字符串值,字符串valueType,字符串发行者,字符串originalIssuer,ClaimsIdentity主题,字符串propertyKey,字符串propertyValue) System.Security.Claims.Claim..ctor(字符串类型,字符串值) Microsoft.AspNetCore.Identity.IdentityUserClaim.ToClaim()
曾希望简化它会成为麻烦,所以我不必重写.AddAspNetIdentity<AppUser>()
,但这没用。显然,不是来自DB的东西为null,而是必须加上它的值为null的东西。我不能说什么,只是它必须在Microsoft.AspNetCore.Identity.IdentityUserClaim<TKey>.ToClaim()
和IdentityServer4.AspNetIdentity.UserClaimsFactory<TUser>.CreateAsync(TUser user) in UserClaimsFactory.cs
之间。我可以肯定地说的是,在https://github.com/IdentityServer/IdentityServer4.AspNetIdentity/blob/dev/src/UserClaimsFactory.cs中,所有在数据库中验证了尝试设置的值是否不为空。
在添加自定义角色之前IDS4仍在工作,这也不值钱。我不是100%不确定这里是否还在发挥作用。
因此,我想知道的是,在我排除的情况下,ID的名称是否是此处的问题。在更新中,AspNetUser的表的表设置为user_id
而不是Id
(Microsoft Owin Security - Claims Constructor Value cannot be null是导致我考虑这一点的原因)。话虽如此,我相信设置没有任何问题,这就是我在OnModelCreating(ModelBuilder builder)
builder.Entity<AppUser>().Property(p => p.Id).HasColumnName("user_id");
到目前为止,在使用它方面还没有任何问题,但是我正在消除将成为问题根源的所有用户差异。
单步执行public class IdentityUserClaim<TKey> where TKey : IEquatable<TKey>
并在Claim ToClaim()
上设置一个断点后,该类型为null。这是日志上的一个问题,但是我似乎无法在其起源的调用堆栈中回溯。我的问题是,如果数据库查询返回一组正确的类型和值,那么为什么要先处理一个空类型和值呢?第一次遇到断点时,类型为null。
在碰到每个断点之后,如果我在这里碰到一个错误,我现在会陷入困境并受伤。我进入UserManager
并按照堆栈进行操作,可以看到主要声明在那里并且可以。
然后下一部分是运行声明存储,该存储执行上面的查询,并在该时间执行失败。我不明白为什么。我在SQL Manager中运行查询,但没有一个NULL
。
有人看到发生了什么事吗?此刻我很茫然。
因此,当我打断设置为null的声明时,没有注意到当地人,我看到我想要的值在this
的范围内
现在的问题是范围如何关闭,我将所需的值放在错误的位置
答案 0 :(得分:0)
这个问题花了一些时间,但是现在很清楚为什么会失败。 AppUserClaim
是真正的问题。很难说,在那一步过分地看着当地人,这就是为什么我不得不在这里走很长一段路。
我曾经的扩展IdentityUserClaim<string>
是
public class AppUserClaim : IdentityUserClaim<string>
{
public int Id { get; set; }
/// <summary>
/// Gets or sets the primary key of the user associated with this claim.
/// </summary>
public virtual string UserId { get; set; }
public virtual AppUser user { get; set; }
/// <summary>
/// Gets or sets the claim type for this claim.
/// </summary>
public virtual string ClaimType { get; set; }
/// <summary>
/// Gets or sets the claim value for this claim.
/// </summary>
public virtual string ClaimValue { get; set; }
}
但是ClaimType
和ClaimValue
的属性不需要重写。一旦完成此操作,它将在方法范围之外的地方设置值。将模型更改为
public class AppUserClaim : IdentityUserClaim<string> {
public virtual AppUser user { get; set; } // note this is the reason why i had to extend
}
解决问题。它没有出现在其他应用程序中,因为声明是在SSO中设置的,因此该方法始终被跳过。
要记住的经验教训,请务必确保在逐步通过时查看当地人。我走了一天才看到寂静的时刻。