【问题标题】:Getting exception while fetching user information using Microsoft Graph in .Net Core 3.1在 .Net Core 3.1 中使用 Microsoft Graph 获取用户信息时出现异常
【发布时间】:2021-07-23 10:50:20
【问题描述】:

我在 .net core 3.1 中创建了一个 Web 应用程序,并针对 Azure AD 对用户进行身份验证。身份验证成功后,我从 Microsoft Graph API 获取用户信息。一切都在本地正常工作,但每当我将它发布到 Azure 时,它​​对于第一次登录但如果用户已经登录(以前登录)到 Web 应用程序的用户也会正常工作。如果已经登录并再次登录的用户注销,此应用程序也可以正常工作。如果用户已经登录并尝试通过 Microsoft Graph 获取用户详细信息,则会出现异常:

Code: generalException
Message: An error occurred sending the request.
 (1b2e028d)
2021-07-23T03:33:27.7510101+00:00 80010cc2-0000-da00-b63f-84710c7967bb [INF]    at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Microsoft.Graph.BaseRequest.SendAsync[T](Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Microsoft.Graph.UserRequest.GetAsync(CancellationToken cancellationToken)
   at SentimentAnalysisApp.Controllers.HomeController.Index() in D:\Workspaces\Controllers\HomeController.cs:line 70 (15cafa0a)

这是我的 Startup.cs:

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)
        {
            string[] initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');

            services
            // Use OpenId authentication
            .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
            // Specify this is a web app and needs auth code flow
            .AddMicrosoftIdentityWebApp(Configuration)
            // Add ability to call web API (Graph)
            // and get access tokens
            .EnableTokenAcquisitionToCallDownstreamApi(options =>
            {
                Configuration.Bind("AzureAd", options);
            }, initialScopes)
            // Use in-memory token cache
            // See https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization
            .AddInMemoryTokenCaches()
            .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"));

            // Require authentication
            services.AddControllersWithViews(options =>
            {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            })
            // Add the Microsoft Identity UI pages for signin/out
            .AddMicrosoftIdentityUI();

            //services.AddSingleton<AppData>();
            services.AddScoped<AppData>();
            

            services.AddRazorPages();

            var path = Directory.GetCurrentDirectory();
            services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo($"{path}\\DataProtectionKeys\\Keys.xml"));

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            var path = Directory.GetCurrentDirectory();
            loggerFactory.AddFile($"{path}\\SentimentLogs\\Sentiment_Log.txt");

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/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.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapRazorPages();
            });
        }
    }

这是我的控制器类:

    [Authorize]
    public class HomeController : Controller
    {
    public HomeController(IConfiguration config, ILogger<HomeController> logger,
                              GraphServiceClient graphServiceClient,
                              ITokenAcquisition tokenAcquisition,
                              IDataProtectionProvider provider, AppData appData,
                               IMemoryCache memoryCache)
            {
                _logger = logger;
                _graphServiceClient = graphServiceClient;
                _tokenAcquisition = tokenAcquisition;
                _protector = provider.CreateProtector("Encrypt");
                _appData = appData;
                _config = config;
    
            }
    
            [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
            public async Task<IActionResult> Index()
            {            
                try
                {
                    //Here I'm fetching logged in user details and getting exception if the user 
                    //already logged in.                
                    LoggedInUser = await _graphServiceClient.Me.Request().GetAsync();
                    _appData.LoggedInUser = LoggedInUser.DisplayName;
                    string token = await _tokenAcquisition.GetAccessTokenForUserAsync(GraphConstants.Scopes);                
                }
                catch (MicrosoftIdentityWebChallengeUserException)
                {
                    return Challenge();
                }
                catch (Exception ex)
                {
                    _logger.LogInformation(ex.Message);
                    _logger.LogInformation(ex.StackTrace);
                    Console.WriteLine(ex.Message);
                    //return Challenge();
                }
    
                return View(_appData);
            }
}

任何帮助将不胜感激!

【问题讨论】:

  • 如果可能的话,您可以根据官方示例代码为我提供不包含任何敏感信息的示例代码。我可以重现问题并更好地帮助您。

标签: c# asp.net-core-mvc asp.net-core-3.1 azure-ad-graph-api microsoft-graph-sdks


【解决方案1】:

我无法根据官方示例代码重现您的问题。但是从您的错误消息中,我看到您的错误消息来自您的本地电脑。

在 D:\Workspaces\Controllers\HomeController.cs:line 70 (15cafa0a) 中的 SentimentAnalysisApp.Controllers.HomeController.Index() 处

你的描述是本地一切正常,但是发布后问题出现了。

所以我给出以下建议并建议故障排除:

  1. 确认门户中是否有本地和发布后的网址

  2. 程序发布时session会被清空,所以在测试功能时,在webapp重新发布之前登录的用户会出现问题。这是正常的。

【讨论】:

  • 嘿,@Jason Pan 感谢您的回复,并为迟到的回复道歉。日志不是来自本地电脑,而是来自托管我的应用程序的应用程序服务。而且我已经设置了您提到的重定向 URI。对于示例代码Click here to know what I'm trying to do
  • @AsifHussain 我测试的时候也使用了这段代码,没有问题。我在测试时也使用了这段代码,没有任何问题。您在代码中添加了很多内容。如果可能,建议重新创建示例示例代码,不包含任何业务或机密信息,以便我们进行复制。你的问题。
  • @AsifHussain 另外,在应用注册中,你做了什么配置?
  • 感谢@Jason Pan 的帮助。我知道这里发生了什么。据我了解,当我第一次登录时,令牌存储在令牌缓存中,每当重新发布时,应用令牌都会被清除,当我发起调用 await _graphServiceClient.Me.Request().GetAsync(); 时,会出现异常。我只是先获取令牌然后发起呼叫,它按预期工作。获取token后调用GraphServiceClient:string token = await _tokenAcquisition.GetAccessTokenForUserAsync(GraphConstants.Scopes);
猜你喜欢
  • 2018-04-06
  • 1970-01-01
  • 2021-01-10
  • 2016-07-23
  • 1970-01-01
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
相关资源
最近更新 更多