AspNetCore 2.1 Bearer Token Authentication - 当前用户为空

Posted

技术标签:

【中文标题】AspNetCore 2.1 Bearer Token Authentication - 当前用户为空【英文标题】:AspNetCore 2.1 Bearer Token Authentication - Current user is empty 【发布时间】:2018-11-13 04:25:52 【问题描述】:

我有一个在用户登录时请求令牌的应用程序。 然后将该令牌与以下标头一起传递:

Authorization: Bearer <TOKEN>

我的startup.cs (aspnet core 2.1) 上有以下代码:

public void ConfigureServices(IServiceCollection services)

    services.AddMvcCore()
            .SetCompatibilityVersion(CompatibilityVersion.Latest)
            .AddFormatterMappings()
            .AddJsonFormatters()
            .AddCors()
            .AddAuthorization(o =>
            
                o.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
                 .RequireAuthenticatedUser()
                 .Build();
            );

    /* Code... */

    ConfigureAuthentication(services);

    /* Code... */


// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    app.UseAuthentication()
       .UseMiddleware<ExceptionMiddleware>(container)
       .UseCors(x =>
       
           x.WithOrigins("*")
           .AllowAnyMethod()
           .AllowCredentials()
           .AllowAnyHeader()
           .Build();
       );

    /* Code... */


private void ConfigureAuthentication(IServiceCollection services)

    services.AddAuthentication(options =>
    
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    )
    .AddJwtBearer(options =>
    
        var tokenProvider = new HumbleTokenProvider(container);
        options.TokenValidationParameters = tokenProvider.GetValidationParameters();
        options.RequireHttpsMetadata = false;
    );

要在用户登录时创建令牌,我有 TokenProvider 服务:

public class RsaJwtTokenProvider : ITokenProvider

    readonly IConfiguration configuration;
    readonly IDateFactory dateFactory;

    readonly RsaSecurityKey _key;
    readonly string _algorithm;
    readonly string _issuer;
    readonly string _audience;

    public RsaJwtTokenProvider(
            IConfiguration configuration,
            IDateFactory dateFactory
        )
    
        this.configuration = configuration;
        this.dateFactory = dateFactory;

        var parameters = new CspParameters  KeyContainerName = configuration.GetSection("TokenAuthentication:SecretKey").Value ;
        var provider = new RSACryptoServiceProvider(2048, parameters);

        _key = new RsaSecurityKey(provider);

        _algorithm = SecurityAlgorithms.RsaSha256Signature;
        _issuer = configuration.GetSection("TokenAuthentication:Issuer").Value;
        _audience = configuration.GetSection("TokenAuthentication:Audience").Value;
    

    public (string Token, int Expires) CreateToken(string userName, string UserId)
    
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

        var claims = new List<Claim>()
        
            new Claim(ClaimTypes.NameIdentifier, UserId),
            new Claim(ClaimTypes.Name, userName)
        ;

        ClaimsIdentity identity = new ClaimsIdentity(claims, "jwt");

        int expiresIn = int.Parse(configuration.GetSection("TokenAuthentication:Validaty").Value);
        DateTime expires = dateFactory.Now.AddMinutes(expiresIn).ToUniversalTime();
        SecurityToken token = tokenHandler.CreateJwtSecurityToken(new SecurityTokenDescriptor
        
            Audience = _audience,
            Issuer = _issuer,
            SigningCredentials = new SigningCredentials(_key, _algorithm),
            Expires = expires,
            Subject = identity
        );

        return (tokenHandler.WriteToken(token), expiresIn);
    

    public TokenValidationParameters GetValidationParameters()
    

        return new TokenValidationParameters
        
            // The signing key must match!
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = _key,

            // Validate the JWT Issuer (iss) claim
            ValidateIssuer = true,
            ValidIssuer = _issuer,
            // Validate the JWT Audience (aud) claim
            ValidateAudience = true,
            ValidAudience = _audience,

            // Validate the token expiry
            ValidateLifetime = true,
            // If you want to allow a certain amount of clock drift, set that here:
            ClockSkew = TimeSpan.Zero
        ;
    

如您所见,AddJwtBearer 中使用的TokenValidationParameters 是由上面的代码GetValidationParameters 提供的。

我对此的第一个看法是,startup 授权/身份验证方法都没有检查令牌,或者至少除了 TokenValidationParameters 之外我没有提供它。

由于 Token 组合,我认为它可以工作,并且服务会分解它以提取当前用户并将其插入 Identity。

但是,当我调用 userManager.GetUserId(user) 时,它返回 null。

public string CurrentUser

    get
    
        var user = accessor.HttpContext?.User;
        if (user != null)
            return userManager.GetUserId(user);
        return null;
    

用户内容如下:

我做错了什么?

截图声明(令牌创建)

更新

在Mohammed Noureldin 的帮助下,我发现我的CurrentUser 财产中没有声明。

[Authorize] 放入我的控制器后,它开始工作。 但是,我也需要它来处理匿名操作...... 有什么想法吗?

【问题讨论】:

我不确定您的确切问题是什么。您的问题是您无法从身份中获取当前登录的用户吗? @MohammedNoureldin 是的,就是这样 好的,请检查我的回答 【参考方案1】:

如果我正确理解了您的问题,您将无法从Identity 获取当前登录的User

您需要将Name 声明添加到您的ClaimsIdentity,这将自动转换为Identity 属性的Name 属性。

这是一个例子:

var claims = new List<Claim>

    new Claim(ClaimTypes.Name, "SomeName or Id")
;

并将您需要的任何其他声明添加到此列表中,然后创建您的ClaimsIdentity

ClaimsIdentity identity = new ClaimsIdentity(claims, "jwt");

更新:

我之前没有注意到您正在尝试在您的授权过程中添加Claims(以及整个Identity)。这不是应该的样子。添加声明应该发生在身份验证中,而不是授权中。

【讨论】:

好的,我明白了,不知何故错过了……我会尽快给你反馈。 将其应用到我的CreateToken 之后,我的userManager 仍然检索空值。我会用它来更新我的代码。 @LeandroSoares,您的 Name 属性现在是否已填充? 我想是的...查看问题末尾的屏幕截图。 @LeandroSoares,我一开始并没有注意到您正在尝试在授权过程中添加声明(以及整个身份)。这不是应该的样子。我猜你想做某事并使用了错误的方式来做这件事。您能否准确描述您想要实现的目标(整个想法)?也许我可以帮助你更多。正如我所说,暂时,你不能做任何其他事情。添加声明应该发生在身份验证中,而不是授权中。

以上是关于AspNetCore 2.1 Bearer Token Authentication - 当前用户为空的主要内容,如果未能解决你的问题,请参考以下文章

使用参考令牌的 ASPNETCore SignalR 身份验证

如何为 ASPNETCore 2.1 应用程序配置 SignalR Cors?

OAuth2 资源服务器在与授权服务器通信时应该使用 Basic 还是 Bearer token auth?

JWT Bearer ASP.Net Core 3.1 用户在服务器上为空白

将 httpHandler 附加到 httpclientFactory webapi aspnetcore 2.1

直接从令牌获取 JWT 声明,ASP Net Core 2.1