首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >AspNetCore 2.1持有者令牌认证-当前用户为空

AspNetCore 2.1持有者令牌认证-当前用户为空
EN

Stack Overflow用户
提问于 2018-06-04 03:43:39
回答 1查看 2.2K关注 0票数 3

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

代码语言:javascript
复制
Authorization: Bearer <TOKEN>

我的startup.cs (aspnet core2.1)上有以下代码:

代码语言:javascript
复制
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服务:

代码语言:javascript
复制
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代码提供的。

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

我假设它工作是因为令牌组合,服务将对其进行分解以提取当前用户并将其插入到标识中。

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

代码语言:javascript
复制
public string CurrentUser
{
    get
    {
        var user = accessor.HttpContext?.User;
        if (user != null)
            return userManager.GetUserId(user);
        return null;
    }
}

user的内容如下:

我做错了什么?

截图声明(令牌创建)

更新

Mohammed Noureldin的帮助下,我发现我的CurrentUser属性中没有声明。

[Authorize]放入我的控制器后,它就开始工作了。然而,我也需要它在匿名操作上工作……有什么想法吗?

EN

回答 1

Stack Overflow用户

发布于 2018-06-04 03:46:38

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

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

下面是一个示例:

代码语言:javascript
复制
var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, "SomeName or Id")
};

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

代码语言:javascript
复制
ClaimsIdentity identity = new ClaimsIdentity(claims, "jwt");

更新:

我之前没有注意到,您正试图在授权过程中添加Claims (以及整个Identity)。事情不应该是这样的。添加声明应该在身份验证内部进行,而不是授权。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50670342

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档