我有一个应用程序,它在用户登录时请求令牌。然后,该令牌与以下标头一起传递:
Authorization: Bearer <TOKEN>
我的startup.cs
(aspnet core2.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
代码提供的。
我对此的第一印象是,除了TokenValidationParameters
之外,没有任何startup
授权/身份验证方法检查令牌,或者至少我没有提供令牌。
我假设它工作是因为令牌组合,服务将对其进行分解以提取当前用户并将其插入到标识中。
然而,当我调用userManager.GetUserId(user)
时,它返回null。
public string CurrentUser
{
get
{
var user = accessor.HttpContext?.User;
if (user != null)
return userManager.GetUserId(user);
return null;
}
}
user的内容如下:
我做错了什么?
截图声明(令牌创建)
更新
在Mohammed Noureldin的帮助下,我发现我的CurrentUser
属性中没有声明。
把[Authorize]
放入我的控制器后,它就开始工作了。然而,我也需要它在匿名操作上工作……有什么想法吗?
发布于 2018-06-04 03:46:38
如果我正确理解了您的问题,您无法从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
)。事情不应该是这样的。添加声明应该在身份验证内部进行,而不是授权。
https://stackoverflow.com/questions/50670342
复制相似问题