微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当用户 ID 类型从字符串更改为整数时,.net 核心中的 User.Identity.IsAuthenticated 始终为 false

如何解决当用户 ID 类型从字符串更改为整数时,.net 核心中的 User.Identity.IsAuthenticated 始终为 false

我有一个使用 json web 令牌进行身份验证的 asp.net 核心应用程序,当我的用户 ID 是字符串时,这工作正常,但在更改为 int 后停止工作。

我的 IdentityUser 类型原来是这个

public class AppUser : IdentityUser
{
     //other properties...
}

我更新了这个;

public class AppUser : IdentityUser<int>
{
     //other properties...
}

我从此更改了启动配置;

        services.Configure<JwtIssuerOptions>(options =>
        {
            options.Issuer = jwtIssuerOptions.Issuer;
            options.Audience = jwtIssuerOptions.Audience;
            options.SigningCredentials = jwtIssuerOptions.SigningCredentials;
        });


        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,Validissuer = jwtIssuerOptions.Issuer,ValidateAudience = true,ValidAudience = jwtIssuerOptions.Audience,ValidateIssuerSigningKey = true,IssuerSigningKey = _signingKey,RequireExpirationTime = false,ValidateLifetime = true,ClockSkew = TimeSpan.Zero
        };

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(configureOptions =>
        {
            configureOptions.ClaimsIssuer = jwtIssuerOptions.Issuer;
            configureOptions.TokenValidationParameters = tokenValidationParameters;
            configureOptions.Savetoken = true;
        });

        // add identity
        var builder = services.AddIdentityCore<AppUser>(o =>
        {
            // configure identity options
            o.Password.requiredigit = false;
            o.Password.RequireLowercase = false;
            o.Password.RequireUppercase = false;
            o.Password.RequireNonAlphanumeric = false;
            o.Password.requiredLength = 6;
            o.SignIn.RequireConfirmedEmail = true;
        });
        builder = new IdentityBuilder(builder.UserType,typeof(IdentityRole),builder.Services);
        builder.AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();

为此;

    services.Configure<JwtIssuerOptions>(options =>
        {
            options.Issuer = jwtIssuerOptions.Issuer;
            options.Audience = jwtIssuerOptions.Audience;
            options.SigningCredentials = jwtIssuerOptions.SigningCredentials;
        });


        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,ClockSkew = TimeSpan.Zero
        };

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(configureOptions =>
        {
            configureOptions.ClaimsIssuer = jwtIssuerOptions.Issuer;
            configureOptions.TokenValidationParameters = tokenValidationParameters;
            configureOptions.Savetoken = true;
        });

        // add identity
        var builder = services.AddIdentity<AppUser,IdentityRole<int>>(o =>
        {
            // configure identity options
            o.Password.requiredigit = false;
            o.Password.RequireLowercase = false;
            o.Password.RequireUppercase = false;
            o.Password.RequireNonAlphanumeric = false;
            o.Password.requiredLength = 6;
            o.SignIn.RequireConfirmedEmail = true;
        });
        builder = new IdentityBuilder(builder.UserType,typeof(IdentityRole<int>),builder.Services);
        builder.AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();

我使用以下方法生成令牌,这在实现之间没有改变。

    public async Task<string> GenerateEncodedToken(string userName,ClaimsIdentity identity)
    {
        var claims = new[]
     {
             new Claim(JwtRegisteredClaimNames.Sub,userName),new Claim(JwtRegisteredClaimNames.Jti,await _jwtOptions.JtiGenerator()),new Claim(JwtRegisteredClaimNames.Iat,ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(),ClaimValueTypes.integer64),identity.FindFirst(JwtClaimIdentifiers.Rol),identity.FindFirst(JwtClaimIdentifiers.Id)
         };

        // Create the JWT security token and encode it.
        var jwt = new JwtSecurityToken(
            issuer: _jwtOptions.Issuer,audience: _jwtOptions.Audience,claims: claims,notBefore: _jwtOptions.NotBefore,expires: _jwtOptions.Expiration,signingCredentials: _jwtOptions.SigningCredentials);

        var encodedJwt = new JwtSecurityTokenHandler().Writetoken(jwt);

        return encodedJwt;
    }

最后这个方法用于创建声明标识;

    public ClaimsIdentity GenerateClaimsIdentity(string userName,int id)
    {
        return new ClaimsIdentity(new GenericIdentity(userName,"Token"),new[]
        {
            new Claim(JwtClaimIdentifiers.Id,id.ToString(),ClaimValueTypes.Integer32),});
    }

User.Identity.IsAuthenticated 现在在验证时始终为 false,并且 ClaimsIdentity 似乎没有我在将 AppUser 从字符串 ID 类型转换为 int Id 类型之前看到的信息。

到目前为止我所掌握的最好的理论是,问题可能与令牌值的序列化/反序列化有关,但我正抓着稻草,不知道如何调试它。

我错过了什么?

解决方法

您的代码中没有任何内容让我生气(看起来主要区别在于您从 AddIdentity 切换到 AddIdentityCore?),但我发现 JWT 身份验证问题,它确实有助于运行应用程序在调试模式下并为 JwtBearerEvents 添加处理程序。
将此添加到您的 Startup .AddJwtBearer 调用中:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddJwtBearer(options =>
    {
      // ... 

      // Add this at the end:
      options.Events = new JwtBearerEvents
      {
        OnAuthenticationFailed = context =>
        {
// Put a breakpoint here
          System.Console.WriteLine(context.Exception);
          return Task.CompletedTask;
        },};
    })

如果您在调试中运行,将能够检查context.Exception

Example Exception inspection

这应该可以让您更好地解释 JWT 身份验证失败的原因。

,

利用 Connor Low's advice,我为所有 JwtBearerOptions 事件提供了委托。这些都没有命中,说明我的设置不够完善,根本没有使用我配置的认证方案。

我恢复到addIdentityCore

var builder = services.AddIdentityCore<AppUser>(o =>

虽然我不能再指定我使用的是 IdentityRole<int> 而不是像这样的默认值;

var builder = services.AddIdentity<AppUser,IdentityRole<int>>(o =>

如果我有以下行,这似乎是不必要的;

builder = new IdentityBuilder(builder.UserType,typeof(IdentityRole<int>),builder.Services);

随着这些更改就位,身份验证起作用了,并且我在 Connor Low 的建议中添加的断点也被击中了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。