有人可以帮我解决这个问题吗?我正在使用Postman测试API
我正在关注有关asp.net核心的教程。
我现在在认证部分。
我不太了解错误的原因。
在本教程中,它具有登录名并返回令牌。
这是登录代码。哪个在工作。我知道这是有效的,因为它返回令牌。我也尝试使用无效的登录名。并返回401 Unauthorized
,但是当我使用数据库中找到的正确登录凭据时。它返回令牌
[HttpPost("login")]
public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
{
var userFromRepo = await _repo.Login(userForLoginDto.Username.ToLower(), userForLoginDto.Password);
if (userFromRepo == null)
return Unauthorized();
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
new Claim(ClaimTypes.Name, userFromRepo.Username)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return Ok(new {
token = tokenHandler.WriteToken(token)
});
}
然后,本教程的下一部分是限制访问。用户应先登录才能查看内容。
下面是代码
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>{
options.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false
};
});
然后启用
app.UseAuthentication();
我还启用了值控制器中的[Authorize]
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
这是邮递员的屏幕截图
我遵循了本教程。我粘贴从登录中收到的令牌。但这给了我错误
WWW-Authenticate →Bearer error="invalid_token", error_description="The audience is invalid"
如果令牌来自登录名,为什么错误会给我invalid token
?我该如何解决?我已经搜寻了一段时间,但我无法解决自己的问题。谢谢。
更新:
错误是因为我忘记了这个
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>{
options.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
答案 0 :(得分:2)
我最近使用JWT令牌做了类似的事情,该令牌与Postman可以很好地工作。我创建JWT令牌的方法几乎没有什么不同,在您的情况下,问题可能是由于未指定 发行人和受众。 >
您可以尝试以下方法吗?
var claims = new List<Claim>
{
new Claim(ClaimTypes.WindowsAccountName, this.User.Identity.Name)
};
Claim userIdClaim = new Claim("UserId", "12345");
claims.Add(userIdClaim);
//Avoid Replay attack
claims.Add(new Claim(ClaimTypes.GivenName, "User GivenName"));
claims.Add(new Claim(ClaimTypes.Surname, "UserSurname"));
claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
string[] roles = "Role1,Role2,Role23".Split(",");
foreach (string role in roles)
{
claims.Add(new Claim(role, ""));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("veryVerySecretKey"));
var key1 = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ASEFRFDDWSDRGYHF"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var encryptingCreds = new EncryptingCredentials(key1, SecurityAlgorithms.Aes128KW, SecurityAlgorithms.Aes128CbcHmacSha256);
var handler = new JwtSecurityTokenHandler();
var t = handler.CreateJwtSecurityToken();
var token = handler.CreateJwtSecurityToken("http://localhost:61768/", "http://localhost:61768/"
, new ClaimsIdentity(claims)
, expires: DateTime.Now.AddMinutes(1)
, signingCredentials: creds
, encryptingCredentials :encryptingCreds
, notBefore:DateTime.Now
, issuedAt:DateTime.Now);
return new JwtSecurityTokenHandler().WriteToken(token);
我的ConfigureServices
看起来像
services.AddAuthentication()
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:61768/",
ValidAudience = "http://localhost:61768/",
TokenDecryptionKey= new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ASEFRFDDWSDRGYHF")),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("veryVerySecretKey")),
ClockSkew = TimeSpan.Zero
};
});
注意:适当更改发行者和密钥。
答案 1 :(得分:1)
我遇到了类似的问题,即.net Core 3 API无法验证其自己的令牌。
对我来说,解决方案是在Startup / Configure()中,将app.UseAuthentication()放在app.UseAuthorization()之前。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
app.UseAuthorization();
}
答案 2 :(得分:0)
收到的错误与受众有关,您应该在选项中包括ValidAudience或将ValidateAudience设置为false。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
答案 3 :(得分:0)
我有同样的问题。请注意配置功能中的顺序。
app.usemvc ();
应该在底部。像这样:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
希望如此可以解决您的问题。
答案 4 :(得分:0)
Ram Kumaran(https://stackoverflow.com/a/54396550/8210755)的答案对我有用,它可能是在更新到Net Core 3.1之后或在将IdentityServer更新到4.3.1之后发生的。
我已经用AddJwtBearer替换了注释的代码
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
//.AddIdentityServerAuthentication(options =>
//{
// options.Authority = Configuration.GetSection("IdentityServerUrl").Value;
// options.RequireHttpsMetadata = false;
// options.ApiName = "api1";
//});
.AddJwtBearer(o =>
{
o.Authority = Configuration.GetSection("IdentityServerUrl").Value;
o.RequireHttpsMetadata = false;
o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateAudience = false
};
});
使用完整的文档参考: https://docs.identityserver.io/_/downloads/en/latest/pdf/ 在类似概念的虚假证明中使用ValidateAudience