postman c#asp.net核心承载错误=“无效令牌”

a0zr77ik  于 2022-11-07  发布在  Postman
关注(0)|答案(9)|浏览(193)

有人能帮我解决这个问题吗?我正在用Postman测试API
我正在学习一个关于asp.net核心的教程。
我现在在它的认证部分。
我真的不明白这个错误的原因是什么。
在教程中,它有一个登录名并返回token。
这是登录的代码。它是有效的。我知道它是有效的,因为它返回一个令牌。我也尝试使用无效的登录。它返回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();

我还在Values Controller中启用了[Authorize]

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

这是 Postman 的截图

我按照教程进行了操作。我粘贴了登录时收到的令牌。但它给了我错误

WWW-Authenticate →Bearer error="invalid_token", error_description="The audience is invalid"

如果令牌是来自登录,为什么错误会给予我invalid token?我该如何解决这个问题?我已经搜索了一段时间,但我自己无法解决这个问题。谢谢。

lpwwtiir

lpwwtiir1#

更新到Microsoft.AspNetCore.Authentication.JwtBearer v6.0.0+后,我在dotnet 6中遇到了此问题
修复后:安装nugetSystem.IdentityModel.Tokens.Jwt Version="6.16.0"

e37o9pze

e37o9pze2#

我也遇到过类似的问题,其中.net Core 3 API不会验证它自己的令牌。
我的解决方案是在Startup/Configure()中,将app.UseAuthentication()放在app.UseAuthorization()之前。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 {
    app.UseAuthentication();

    app.UseAuthorization();
 }
v9tzhpje

v9tzhpje3#

我最近使用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
                 };
             });

注意:请适当地更改颁发者和密钥。

inn6fuwd

inn6fuwd4#

您收到的错误与访问群体相关,您应该在选项中包含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
          };
        });
im9ewurl

im9ewurl5#

我也遇到了同样的问题。请注意配置功能中的顺序。
app.usemvc ();应该位于底部。如下所示:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseAuthentication();
    app.UseMvc();
}
idfiyjo8

idfiyjo86#

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,例如false

uqzxnwby

uqzxnwby7#

在我的例子中(使用Keycloak),我添加了一个新领域,但忘记更改Authorization和Jwt承载元数据的url。它们仍然指向旧领域。我将领域名称从门户更改为测试门户,提供的令牌不正确,因为它仍然来自门户领域。
取自我的appsettings.json:

"AuthorizationUrl": "https://my.keycloak.id.provider/realms/test-portal/protocol/openid-connect/auth",
"JwtBearerMetadataAddress": "https://my.keycloak.id.provider/realms/test-portal/.well-known/openid-configuration"
6rqinv9w

6rqinv9w8#

我正在寻找一个类似的问题,但不是这个,
在appsettings.json中,您需要添加一个JWTSection,并使用它们来验证令牌的颁发者和受众,使令牌更安全
如果您查看错误的描述:访问群体无效

"BearerToken": {
"Issuer": "the api host",
"Audience": "who use the token",
"Key": "a key to validate your token",
"AccessTokenExpirationMinutes": 25,
"RefreshTokenExpirationMinutes": 50

},
添加令牌描述符时,必须在其中添加颁发者和受众

var descriptor = new SecurityTokenDescriptor
            {
                Issuer = _configuration.Value.Issuer,
                Audience = _configuration.Value.Audience,
                Expires = Clock.UtcNow.ExpiresInMinutes(_configuration.Value.AccessTokenExpirationMinutes),
                Subject = new ClaimsIdentity(userClaims),
                SigningCredentials = new SigningCredentials(authSignInKey, SecurityAlgorithms.HmacSha256),
            };

和启动类(.NET 5或更早版本)或程序(.NET 6)中
您需要添加这样的身份验证服务来验证令牌

builder.Services.AddAuthentication(option =>
{
    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;

}).AddJwtBearer(options =>
{
      options.SaveToken = true;
      options.RequireHttpsMetadata = false;
      options.TokenValidationParameters = new TokenValidationParameters
      {
          ValidateIssuer = true,
          ValidateAudience = true,
          ValidateLifetime = true,
          ValidateIssuerSigningKey = true,
          ValidIssuer = builder.Configuration["BearerToken:Issuer"],
          ValidAudience = builder.Configuration["BearerToken:Audience"],
          IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(builder.Configuration["BearerToken:Key"])),
      };
});
ee7vknir

ee7vknir9#

对我来说,我的JwtSecurityToken构造函数的参数是不正确的。在构造函数上有一些可以为空的参数,所以我需要定义哪个是哪个。例如,我有...

new JwtSecurityToken(issuer, audience, claims, expires, signingCredentials: credentials);

这就修好了。

new JwtSecurityToken(issuer, audience, claims, expires: expires, signingCredentials: credentials);

也许其他人很难遇到这种情况,但嘿,它发生在我身上。

相关问题