繁体   English   中英

在 Blazor 服务器应用程序中,是否可以将 GraphServiceClient 注入范围服务?

[英]In a Blazor Server app, is it possible to inject a GraphServiceClient into a scoped service?

我一直在试验新的 Blazor 功能,并试图将用户数据从 Azure AD 提取到测试应用程序中。 这些是相关的片段:

我的服务

public class UserService
{

    GraphServiceClient _graphClient { get; set; }
    protected User _user = null;

    public UserService(GraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    public string GetUserName()
    {
        return User()?.DisplayName ?? "";
    }

启动

public void ConfigureServices(IServiceCollection services)
    {
        var initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');

        services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)

            // Add sign-in with Microsoft
            .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))

            // Add the possibility of acquiring a token to call a protected web API
            .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)

                   // Enables controllers and pages to get GraphServiceClient by dependency injection
                   // And use an in memory token cache
                   .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
                   .AddInMemoryTokenCaches();

        services.AddControllersWithViews()
            .AddMicrosoftIdentityUI();

        services.AddRazorPages()
            .AddMicrosoftIdentityUI();
        services.AddServerSideBlazor()
            .AddMicrosoftIdentityConsentHandler();

        services.AddSingleton<WeatherForecastService>();
        services.AddScoped<UserService>();

GraphServiceClient 确实在 my.cs 脚本中初始化,但我收到错误消息:

错误:没有帐户或登录提示传递给 AcquireTokenSilent 调用

任何 azure 配置都不是问题(我认为),因为如果我使用 Microsoft 示例并制作 ComponentBase,一切正常。

public class UserProfileBase : ComponentBase
{
    [Inject]
    GraphServiceClient GraphClient { get; set; }

    protected User _user = new User();
    protected override async Task OnInitializedAsync()
    {
        await GetUserProfile();
    }

    /// <summary>
    /// Retrieves user information from Microsoft Graph /me endpoint.
    /// </summary>
    /// <returns></returns>
    private async Task GetUserProfile()
    {
        try
        {
            var request = GraphClient.Me.Request();
            _user = await request.GetAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

我目前的想法是,即使我已经通过身份验证,配置文件组件使用的 Authorize 标记(以及 ComponentBase?)正在使用访问令牌在幕后做一些事情?

@page "/profile"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inherits UserProfileBase
public class UserAccount
{
 public int Id {get; set;}
 public string FirstName {get; set;}
 public string LastName {get; set;}
 public string Email {get; set;}
}
public class UserService
{

  GraphServiceClient _graphClient;
  protected UserAccount _user {get; set;}

  public UserService(GraphServiceClient graphClient)
  {
    _graphClient = graphClient;
  }
  public async Task<string> GetUserName()
  {
    UserAccount = await GetUserAsync();
    return $"{UserAccount.FirstName} {UserAccount.LastName}";
  }
  public async Task<UserAccount> GetUserAsync()
  {
    var user = awiat __graphClient.Me.Request.Select( e => new
       {
         e.Id,
         e.GivenName,
         e.Surname,
         e.Identities,
       }).GetAsync();
    if(user != null)
    {
      var email = user.Identities.ToList().FirstOrDefault(x => x.SignInType == "emailAddress")?.IssuerAssignedId;
      return new UserAccount
         {
           Id= user.Id,
           FirstName= user.GivenName,
           LastName= user.Surname,
           Email= email
         };
    }
    else {return null;}
  }
}

抱歉,这个答案晚了一年多 - 希望这会在未来对其他人有所帮助。 我今天也试图解决这个确切的问题,我从这个演示项目中得到了这个难题的缺失部分。

除了ConfigureServices方法之外,您还需要确保在端点中映射了控制器,以便身份 UI 可以 map 响应。

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers(); // Important for Microsoft Identity UI
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToPage("/_Host");
});

然后你需要对你的作用域服务进行一些异常处理。 我很确定这是因为 Blazor 的预渲染功能最初并未在第一次渲染中对用户进行身份验证。 但不要引用我的话

我看不到 OP 的服务,所以这是我的:

using Microsoft.Graph;
using Microsoft.Identity.Web;

namespace MyProject.Services
{
    public class UserService
    {
        private readonly GraphServiceClient _graphServiceClient;
        private readonly MicrosoftIdentityConsentAndConditionalAccessHandler _consentHandler;

        public UserService(
            GraphServiceClient graphServiceClient,
            MicrosoftIdentityConsentAndConditionalAccessHandler consentHandler)
        {
            _graphServiceClient = graphServiceClient;
            _consentHandler = consentHandler;
        }

        public async Task<User?> GetUserAsync()
        {
            try
            {
                return await _graphServiceClient.Me.Request().GetAsync();
            }
            catch (Exception ex)
            {
                _consentHandler.HandleException(ex);
                return null;
            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM