无法调用带有[Authorize(Roles = "角色名称")]属性标记的方法。 ASP.NET Core

问题描述 投票:0回答:1

因此,我做了一个简单的 Jwt 令牌授权。当没有角色时,一切都正常。但是,当我尝试使该方法只能通过角色访问时,它显示 403 和其他访问错误。

我的程序.cs:

        var builder = WebApplication.CreateBuilder(args);

        var Origins = "restaraunt-react-ap";

        builder.Services.AddTransient<ICheckLoginService, CheckLoginService>();
        builder.Services.AddTransient<IRestaurantTPDbContext, RestaurantTPDbContext>();
        builder.Services.AddTransient<IJWTService, JWTService>();
        builder.Services.AddTransient<IRoleService, RoleService>();

        builder.Services.AddDefaultIdentity<IdentityUser>().AddRoles<IdentityRole>().AddEntityFrameworkStores<RestarauntTPDBIdentityDBContext>();

        builder.Services.AddAuthorization(option =>
        {
            option.AddPolicy("admin", policyBuilder => policyBuilder.RequireClaim("admin", "waiter", "cook"));
        });
        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = AuthOptions.ISSUER,
                    ValidateAudience = true,
                    ValidAudience = AuthOptions.AUDIENCE,
                    ValidateLifetime = true,
                    IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(),
                    ValidateIssuerSigningKey = true,
                };
            });

        builder.Services.AddControllers();
        builder.Services.AddEndpointsApiExplorer();
        builder.Services.AddHttpContextAccessor();

        builder.Services.AddSwaggerGen();
        builder.Services.AddCors(options =>
            options.AddPolicy(Origins, policy =>
            {                policy.WithOrigins("http://localhost:3000/").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
            }));

        builder.Services.AddDbContext<RestaurantTPDbContext>(options => options.UseSqlServer("Server = NANOMACHINE; Database = RestaurantTP; Trusted_Connection=True; TrustServerCertificate=true;"));
        builder.Services.AddDbContext<RestarauntTPDBIdentityDBContext>(options => options.UseSqlServer("Server = NANOMACHINE; Database = RestaurantTP; Trusted_Connection=True; TrustServerCertificate=true;"));

var app = builder.Build();

        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

        app.UseHttpsRedirection();

        app.UseAuthorization();
        app.UseCors(Origins);
app.MapControllers();

app.Run();

新的DbContext:

public class RestarauntTPDBIdentityDBContext : IdentityDbContext<IdentityUser>
 {
     public DbSet<IdentityRole> roles { get; set; }

     public RestarauntTPDBIdentityDBContext(DbContextOptions<RestarauntTPDBIdentityDBContext> options) : base(options)
     {

     }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
     {
         optionsBuilder.UseSqlServer("Server = NANOMACHINE; Database = RestaurantTP; Trusted_Connection=True; TrustServerCertificate=true;");
     }
 }

我的角色服务

public class RoleService : IRoleService
{
    private readonly IServiceProvider _serviceProvider;

    public RoleService(IServiceProvider serviceProvider)
    { 
        _serviceProvider = serviceProvider;
    }

    public async Task SetRoles()
    {
        var roleManager = _serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

        string[] roleNames = { "administrator", "cook", "waiter" };

        foreach (var roleName in roleNames)
        {
            bool roleExists = await roleManager.RoleExistsAsync(roleName);
            if (!roleExists)
            {
                await roleManager.CreateAsync(new IdentityRole(roleName));
            }
        }
    }

}

代币生成器

public class JWTService : IJWTService
{
    public readonly IRoleService _roleService;
    public JWTService(IRoleService roleService) 
    {
        _roleService = roleService;
    }
    public string GenerateToken(string name, string role)
    {

        var claims = new List<Claim> { new Claim(ClaimsIdentity.DefaultNameClaimType, name, ClaimsIdentity.DefaultRoleClaimType, role) };

        var jwt = new JwtSecurityToken(
            issuer: AuthOptions.ISSUER,
            audience: AuthOptions.AUDIENCE,
            claims: claims,
            expires: DateTime.Now.AddSeconds(20),
            signingCredentials: new SigningCredentials(AuthOptions.GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256)
            );
  
        return new JwtSecurityTokenHandler().WriteToken(jwt);
    }

}

我的控制器

[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
    private readonly ICheckLoginService _checkLoginService;
    private readonly IRoleService _roleService;

    public AuthenticationController(ICheckLoginService checkLoginService, IRoleService roleService)
    {
        _checkLoginService = checkLoginService;
        _roleService = roleService;
    }
    
    [HttpGet]
    [Route("gettest")]
    public IActionResult GetData()
    {
        var data = new { Message = "Hello from ASP.NET Core Web API" };
        return Ok(data);
    }

    [HttpPost]
    [Route("sendData")]
    public async Task<IActionResult> TryLogin([FromBody] AutRequest autRequest)
    {
        await Task.Run(() => _roleService.SetRoles());

        var validate = _checkLoginService.Login(autRequest);

        return Ok(validate);
    }

    [HttpGet]
    [Authorize(Roles = "admin")]
    [Route("getSecretInfo")]
    public IActionResult GetSecretInfo()
    {
        return Ok("QWERTY");
    }

    public record AutRequest(string name, string password);
}

我创建了一个新的 DBContext 并在数据库中注册了角色(使用我的 RoleService),但是它不起作用:(

不太明白新的DBContext的作用,但是角色都注册在那里了。我还检查了对服务器的其他请求是否有效,但需要授权和角色的方法不起作用。

c# asp.net-core authentication
1个回答
0
投票
public string GenerateToken(string name, string role)
{
    var claims = new List<Claim> { new Claim(ClaimsIdentity.DefaultNameClaimType, name, ClaimsIdentity.DefaultRoleClaimType, role) };

    var jwt = new JwtSecurityToken(
        issuer: AuthOptions.ISSUER,
        audience: AuthOptions.AUDIENCE,
        claims: claims,
        expires: DateTime.Now.AddSeconds(20),
        signingCredentials: new SigningCredentials(AuthOptions.GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256)
        );

    return new JwtSecurityTokenHandler().WriteToken(jwt);
}

在此方法中,您将使用

this 构造函数
创建仅包含一个 ClaimsIdentity.DefaultNameClaimType 类型的声明的声明列表,我相信这并没有达到您期望的效果。相反,您应该对要在令牌中传递的每条信息有多个声明。

所以你的方法应该如下所示:

ublic string GenerateToken(string name, string role)
{
    var claims = new List<Claim>
    {
        new Claim(ClaimsIdentity.DefaultNameClaimType, name),
        new Claim(ClaimsIdentity.DefaultRoleClaimType, role)
    };

    var jwt = new JwtSecurityToken(
        issuer: AuthOptions.ISSUER,
        audience: AuthOptions.AUDIENCE,
        claims: claims,
        expires: DateTime.Now.AddSeconds(20),
        signingCredentials: new SigningCredentials(AuthOptions.GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256)
    );

    return new JwtSecurityTokenHandler().WriteToken(jwt);
}

进行此类修改后,您确实将在令牌中写入角色声明,并且授权应该可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.