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 用户在服务器上为空白