Почему я не могу использовать авторизацию ролей в моем контроллере API - PullRequest
0 голосов
/ 26 февраля 2020

Я создал проект реагирования с шаблоном реакции в ядре asp. net с индивидуальными учетными записями пользователей. Я осмотрелся и обнаружил, что мне нужно добавить роли в файле запуска и добавить службу профилей, которая, кажется, работает наполовину.

Я могу видеть роли в моем токене авторизации следующим образом:

"role": [
    "admin",
    "bookkeeping" ], 

Но когда я добавляю тег [Authorize(Roles = "admin")] к своему контроллеру, запросы теперь запрещаются, даже когда я вижу, что мой токен включает роль "admin".

Что я здесь упускаю или делаю неправильно?

Это служба профиля:

public class ProfileService : IProfileService
{
    protected UserManager<ApplicationUser> mUserManager;

    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        mUserManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        ApplicationUser user = await mUserManager.GetUserAsync(context.Subject);

        IList<string> roles = await mUserManager.GetRolesAsync(user);

        IList<Claim> roleClaims = new List<Claim>();
        foreach (string role in roles)
        {
            roleClaims.Add(new Claim(JwtClaimTypes.Role, role));
        }
        context.IssuedClaims.Add(new Claim(JwtClaimTypes.Name, user.UserName));
        context.IssuedClaims.AddRange(roleClaims);
    }

    public Task IsActiveAsync(IsActiveContext context)
    {
        return Task.CompletedTask;
    }
}

, и это мой файл запуска:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddRoles<IdentityRole>()
            .AddRoleManager<RoleManager<IdentityRole>>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddIdentityServer()
            .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

        services.AddAuthentication()
            .AddIdentityServerJwt();

        services.AddAuthorization(options =>
        {
            options.AddPolicy("RequireAdministratorRole",
                 policy => policy.RequireRole("admin"));
        });

        services.AddTransient<IProfileService, ProfileService>();
        services.AddControllersWithViews()
            .AddNewtonsoftJson(options =>
                options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );
        services.AddRazorPages();

        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseIdentityServer();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";
            if (env.IsDevelopment())
            {
                spa.UseReactDevelopmentServer(npmScript: "start");
            }
        });
    }
}

Небольшая версия моего контроллера API:

[Authorize(Roles = "admin")]
[Route("api/[controller]")]
public class SampleDataController : ControllerBase
{
    private readonly ApplicationDbContext _db;

    public SampleDataController(ApplicationDbContext db)
    {
        _db = db;
    }   
    [HttpGet("[action]")]
    public IEnumerable<Order> GetOrderList()
    {

        return _db.Order.ToList();
    }

}

И мой метод выборки

async populateOrderList() {
    const token = await authService.getAccessToken();
    const response = await fetch('api/SampleData/GetOrderList', {
        headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
    });
    const data = await response.json();
    this.setState({ orderList: data });
}

Как вы можете видеть в моем файле запуска, я также пытался использовать политику с вместо этого тег [Authorize(Policy = "RequireAdministratorRole")]. Также он отлично работает, когда я просто использую [Authorize]

Редактировать: Мои контроллеры API находятся в том же проекте, что и мой сервер идентификации.

Спасибо за помощь заранее.

1 Ответ

2 голосов
/ 26 февраля 2020

изменить тип заявки по умолчанию для роли в автозагрузке следующим образом:

        services.Configure<IdentityOptions>(options =>
        {
            options.ClaimsIdentity.RoleClaimType = JwtClaimTypes.Role;
        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...