代码之家  ›  专栏  ›  技术社区  ›  A_AhMaD

当我正确配置所有内容以验证用户时,为什么我的端点返回“401未授权”?

  •  1
  • A_AhMaD  · 技术社区  · 1 年前

    我有一个问题,当用户登录并在响应中发送他的JWT令牌时,当他试图访问授权端点时,它总是返回401。我不知道为什么即使他有JWT,他也没有通过身份验证?

    这是程序.cs代码:

    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.IdentityModel.Tokens;
    using Microsoft.OpenApi.Models;
    using ProuductsShopWepAPI.Models;
    using ProuductsShopWepAPI.Reopositories;
    using ProuductsShopWepAPI.RepositoriesContracts;
    using ProuductsShopWepAPI.Services;
    using ProuductsShopWepAPI.ServicesContracts;
    using System.Text;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    
    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(options =>
    {
    
        options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            In = ParameterLocation.Header,
            Description = "Please enter a valid token",
            Name = "Authorization",
            Type = SecuritySchemeType.Http,
            BearerFormat = "JWT",
            Scheme = "Bearer"
        });
        options.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Type=ReferenceType.SecurityScheme,
                        Id="Bearer"
                    }
                },
                Array.Empty<string>()
            }
        });
    });
    
    
    // Add Api services
    builder.Services.AddScoped<IProductRepository, ProductRepository>();
    builder.Services.AddScoped<ICategoryRepository, CategoryRepository>();
    builder.Services.AddScoped<IAccountService, AccountService>();
    
    // Configure Entity frame work
    builder.Services.AddDbContext<ApplicationDbContext>(options =>
    {
        options.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
    });
    
    // Configure jwt authentication
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuer = true,
                ValidIssuer = builder.Configuration["JWT:Issuer"],
                ValidateAudience = true,
                ValidAudience = builder.Configuration["JWT:Audience"],
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"])),
            };
        });
    
    //Configure Identity
    builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
    {
        options.User.RequireUniqueEmail = true;
        options.Password.RequiredUniqueChars = 5;
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequiredLength = 8;
        options.Password.RequireUppercase = true;
    }).AddEntityFrameworkStores<ApplicationDbContext>();
    
    
    //Configure CORS
    builder.Services.AddCors(options =>
    {
        options.AddDefaultPolicy(policy =>
        {
            policy.AllowAnyHeader();
            policy.AllowAnyMethod();
            policy.AllowAnyOrigin();
    
        });
    });
    
    
    builder.Services.ConfigureApplicationCookie(options =>
    {
        options.Events.OnRedirectToAccessDenied =
            options.Events.OnRedirectToLogin = (context) =>
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return Task.FromResult<object>(null);
            };
    });
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    
    app.UseHttpsRedirection();
    app.UseCors();
    app.UseResponseCaching();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    
    app.Run();
    
    

    这是生成JWT令牌的代码:

    public async Task<JwtSecurityToken> CreateJwtAsync(LoginDTO loginDTO)
    {
        var user = new IdentityUser()
        {
            Email = loginDTO.Email
        };
        var issuer = _configuration["JWT:Issuer"];
        var audience = _configuration["JWT:Audience"];
        var key = _configuration["JWT:key"];
    
        var signingCredintials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)), SecurityAlgorithms.HmacSha256);
    
        var roles = await _userManager.GetRolesAsync(user);
        var claims = await _userManager.GetClaimsAsync(user) ?? new List<Claim>();
    
        foreach (var role in roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role));
        }
        claims.Add(new Claim(ClaimTypes.Name, loginDTO.Email));
    
        var jwtObject = new JwtSecurityToken(
            issuer: issuer,
            audience: audience,
            claims: claims,
            expires: DateTime.UtcNow.AddSeconds(1000),
            signingCredentials: signingCredintials
            );
    
        return jwtObject;
    
    }
    

    登录终结点:

        [HttpPost]
        public async Task<IActionResult> Login(LoginDTO loginDTO)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    var details = new ValidationProblemDetails(ModelState);
                    details.Status = StatusCodes.Status400BadRequest;
                    return BadRequest(details);
                }
                var isLoginValid = await _accountService.IsLoginValidAsync(loginDTO);
    
                if (!isLoginValid) throw new Exception("Email or password is not valid");
    
                var jwtObject = await _accountService.CreateJwtAsync(loginDTO);
    
                var stringJwt = new JwtSecurityTokenHandler().WriteToken(jwtObject);
                HttpContext.Response.Headers["Authorization"] = stringJwt;
                return StatusCode(StatusCodes.Status200OK, stringJwt);
    
            }
            catch (Exception ex)
            {
                var problemDetails = new ProblemDetails();
                problemDetails.Detail = ex.Message;
                problemDetails.Status = StatusCodes.Status400BadRequest;
                return StatusCode(StatusCodes.Status400BadRequest, problemDetails);
            }
    
        }
    

    这是种子/类别端点

        [HttpPost]
        [Authorize]
        public async Task<IActionResult> Categories()
        {
            var newCategoriees = new List<Category>();
            using (var reader = new StreamReader($"{_environment.ContentRootPath}/Data/amazon_categories.csv"))
            {
                using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
                {
                    var dic = _categoryRepository.GetAll();
                    var dic1 = await dic.ToDictionaryAsync(c => c.Id);
                    var categories = csv.GetRecordsAsync<ProductCategorie>();
                    await foreach (var category in categories)
                    {
                        if (!dic1.ContainsKey(long.Parse(category.id)))
                        {
                            var newCategory = new Category();
                            newCategory.Id = long.Parse(category.id);
                            newCategory.Name = category.category_name;
                            newCategoriees.Add(newCategory);
                        }
                    }
                }
            }
            await _categoryRepository.AddCategoriesAsync(newCategoriees);
            return StatusCode(StatusCodes.Status200OK, $"{newCategoriees.Count} categories has been added");
    
        }
    

    正如您在这里看到的,即使用户在请求头中有授权,它也会返回401状态代码错误,而不是让他在数据库中播种类别 enter image description here 如果你知道如何解决这个问题,请告诉我。

    2 回复  |  直到 1 年前
        1
  •  1
  •   Alex    1 年前

    在类别端点中,替换 [Authorize] 具有

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    
        2
  •  1
  •   ISR    1 年前

    例如,您可以使用控制器或操作的Authorize属性(您可能对/[controller]/[action]使用了不正确的AuthenticationSchemes)

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]