【问题标题】:Add custom roles for blazor Server side with AzureAd使用 AzureAd 为 blazor 服务器端添加自定义角色
【发布时间】:2022-01-17 01:21:36
【问题描述】:

我有一个中间件,在登录后使用AzureAd 向用户添加自定义角色,它工作正常,但我有一个问题,例如在我登录并且有人也在我之后登录后,这个用户仍然有我为我添加的相同角色。我的问题:为什么 blazor 通过这种方式即使在退出后也会为不同的用户保存这个角色?我想了解背后的机制
这是中间件

public class RoleHandler
{
    private readonly RequestDelegate _next;
    private List<string> Roles { get; set; }

    public RoleHandler(RequestDelegate Next)
    {
        _next = Next;
    }

    public async Task InvokeAsync(HttpContext context, IGenericHttpClient<Role> httpClient)
    {
        if (Roles == null || Roles.Count == 0)
        {
            Roles = await GetRole(context, httpClient);
        }
        else
        {
            foreach (var role in Roles)
            {
                //Add roles to this user, in this case user can be admin or developer ...
                context.User.Identities.FirstOrDefault().AddClaim(new Claim(ClaimTypes.Role, role));
            }
        }
        await _next(context);
    }

    public async Task<List<string>> GetRole(HttpContext context, IGenericHttpClient<Role> httpClient)
    {
        List<string> rolesList = new();
        //Get role from api like [guid, admin]
        var appUserRoles = await httpClient.GetJsonAsync("/api/roles/search?id=XXX");
        //Get role from user as guid
        var RolesString = context.User.Claims
                .Select(c => c.Value).ToList();

        foreach (var appRole in appUserRoles)
        {
            foreach (var role in RolesString)
            {
                if (appRole.RoleString == role)
                {
                    rolesList.Add(appRole.Name);
                }
            }
        }
        return rolesList;
    }
}

启动中的配置服务

        public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<ILoggerManager, LoggerManager>();

        var initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');

        JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

        services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
                .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
                    .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                    .AddInMemoryTokenCaches();

        services.AddScoped(typeof(IGenericHttpClient<>), typeof(GenericHttpClient<>));

        services.AddControllersWithViews()
            .AddMicrosoftIdentityUI();

        services.AddAuthorization(options =>
        {
            // By default, all incoming requests will be authorized according to the default policy
            options.FallbackPolicy = options.DefaultPolicy;
        });

        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddRazorPages();
        services.AddServerSideBlazor()
            .AddMicrosoftIdentityConsentHandler();
    }

GenericHttpClient

public class GenericHttpClient<T> : IGenericHttpClient<T> where T : class
{
    private readonly IHttpClientFactory _clientFactory;
    private HttpClient _client;
    private readonly IConfiguration _configuration;
    public GenericHttpClient(IHttpClientFactory clientFactory,
        IConfiguration configuration)
    {
        _clientFactory = clientFactory;
        _configuration = configuration;

        _client = _clientFactory.CreateClient();

        _client.BaseAddress = new Uri("https://localhost");
    }
    
    public async ValueTask<List<T>> GetJsonAsync(string url)
    {
        using HttpResponseMessage response = await _client.GetAsync(url);
        ValidateResponse(response);
        var content = await ValidateContent(response).ReadAsStringAsync();
        return JsonSerializer.Deserialize<List<T>>(content, new JsonSerializerOptions() { PropertyNameCaseInsensitive=true});
    }
    // ......
}

}

【问题讨论】:

  • 哪里可以找到GenericHttpClient&lt;&gt;的实现?该行为可能通过缓存和重用GenericHttpClient&lt;&gt; 来解释,但如果不知道GenericHttpClient&lt;&gt; 的详细信息,则很难确认。

标签: c# azure asp.net-core blazor blazor-server-side


【解决方案1】:

【讨论】:

  • 感谢@Jason Pan 的回答,我添加了ConfigureServicesStartup,我认为我使用了AddScoped。请看services.AddScoped(typeof(IGenericHttpClient&lt;&gt;), typeof(GenericHttpClient&lt;&gt;));
  • 你能解释一下吗?因为你刚才说试着那样做......我的主要问题是我不明白为什么 blazor 在为每个下一个用户登录后会保存第一个用户的角色。关于使用services.AddHttpClien,我在IGenericHttpClient中使用IHttpClientFactory添加基址
猜你喜欢
  • 1970-01-01
  • 2020-06-22
  • 2022-11-15
  • 1970-01-01
  • 2020-09-19
  • 2020-12-27
  • 2021-12-09
  • 2020-03-25
  • 2021-04-20
相关资源
最近更新 更多