c# - 使用依赖注入(inject)将 token 获取从startup.cs传递到HomeController.cs

标签 c# .net asp.net-core dependency-injection asp.net-core-mvc

我正在尝试从 Startup.cs 文件中为以下代码创建 DI。但作为 .net 的新手,我很难找到解决方案。

var tokenAcquisition = context.HttpContext.RequestServices
     .GetRequiredService<ITokenAcquisition>() as ITokenAcquisition;

var graphClient = GraphServiceClientFactory
    .GetAuthenticatedGraphClient(async () =>
    {
        return await tokenAcquisition
            .GetAccessTokenForUserAsync(GraphConstants.Scopes);
    }
);

启动.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.InMemory;
using Microsoft.Identity.Web.UI;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.Graph;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AD_Lookup
{
    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.AddRazorPages().AddRazorRuntimeCompilation();
            // Add Microsoft Identity Platform sign-in
            services.AddSignIn(options =>
            {
                Configuration.Bind("AzureAd", options);

                options.Prompt = "select_account";

                var authCodeHandler = options.Events.OnAuthorizationCodeReceived;
                options.Events.OnAuthorizationCodeReceived = async context => {
                    // Invoke the original handler first
                    // This allows the Microsoft.Identity.Web library to
                    // add the user to its token cache
                    await authCodeHandler(context);

                    var tokenAcquisition = context.HttpContext.RequestServices
                        .GetRequiredService<ITokenAcquisition>() as ITokenAcquisition;

                    var graphClient = GraphServiceClientFactory
                        .GetAuthenticatedGraphClient(async () =>
                        {
                            return await tokenAcquisition
                                .GetAccessTokenForUserAsync(GraphConstants.Scopes);
                        }
                    );

                    // Get user information from Graph
                    var user = await graphClient.Users["<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c2a1a3b0b4a3aeaaadb1b6a7b2aaa7acf0f282aaadb6afa3abaeeca1adaf" rel="noreferrer noopener nofollow">[email protected]</a>"]
                        .Request()
                        .GetAsync();

                    context.Principal.AddUserGraphInfo(user);

                };


                options.Events.OnAuthenticationFailed = context => {
                    var error = WebUtility.UrlEncode(context.Exception.Message);
                    context.Response
                        .Redirect($"/Home/ErrorWithMessage?message=Authentication+error&debug={error}");
                    context.HandleResponse();

                    return Task.FromResult(0);
                };

                options.Events.OnRemoteFailure = context => {
                    if (context.Failure is OpenIdConnectProtocolException)
                    {
                        var error = WebUtility.UrlEncode(context.Failure.Message);
                        context.Response
                            .Redirect($"/Home/ErrorWithMessage?message=Sign+in+error&debug={error}");
                        context.HandleResponse();
                    }

                    return Task.FromResult(0);
                };
            }, options =>
            {
                Configuration.Bind("AzureAd", options);
            });

            

            // Add ability to call web API (Graph)
            // and get access tokens
            services.AddWebAppCallsProtectedWebApi(Configuration,
                GraphConstants.Scopes)
                // Use in-memory token cache
                // See https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization
                .AddInMemoryTokenCaches();

            // 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();
        }

        // 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();
            //}
            //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.UseDeveloperExceptionPage();
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

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

Homecontroller.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using AD_Lookup.Models;
using Microsoft.Graph;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.InMemory;
using Microsoft.Identity.Web.UI;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AD_Lookup.Controllers
{

    public class HomeController : Controller
    {

    private readonly ILogger<HomeController> _logger;
        private ITokenAcquisition _tokenAcquisition;

        public HomeController(ILogger<HomeController> logger, ITokenAcquisition tokenAcquisition)
        {
            _logger = logger;
            _tokenAcquisition = tokenAcquisition;
        }


        public IActionResult Index()
        {
            return View();
        }

        
        public IActionResult UserSearch()
        {
            //string searchText = model.SearchBoxText;
            //ViewData["searchData"] = searchText;
            return View();
        }

        [HttpPost, ValidateAntiForgeryToken]
        public async Task<IActionResult> SearchBox(UserSearchModel model)
        {
            string searchText = model.SearchBoxText;
            ViewData["searchData"] = searchText;

            var tokenAcquisition = this.HttpContext.RequestServices
                    .GetRequiredService<ITokenAcquisition>() as ITokenAcquisition;

            var graphClient = GraphServiceClientFactory
                    .GetAuthenticatedGraphClient(async () =>
                    {
                        var accessToken =
 await tokenAcquisition.GetAccessTokenForUserAsync(GraphConstants.Scopes, "2b51e32f-e865-48ef-b075-0a456dc76468");
                        return accessToken;
                        //    .GetAccessTokenForUserAsync(GraphConstants.Scopes, "2b51e32f-e865-48ef-b075-0a456dc76468");
                    }
                );
            var user = await graphClient.Users[searchText]
                    .Request()
                    .GetAsync();

            return View();
            //return Content($"Hello {model.SearchBoxText}");
        }

        public IActionResult GroupSearch()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

我不想在 Controller 中复制相同的代码,而是想使用 DI 传递 tokenacquisition 的值。

使用图形 API,我尝试根据文本框中输入的电子邮件 ID 打印用户信息。 graphAPI 提供了我尝试实现的以下代码片段。

GraphServiceClient graphClient = new GraphServiceClient( authProvider );

var user = await graphClient.Users["<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c0f0d1e1a0d0004031f18091c0409025e5c2c040318010d0500420f0301" rel="noreferrer noopener nofollow">[email protected]</a>"]
    .Request()
    .GetAsync();

这可以在 https://developer.microsoft.com/en-us/graph/graph-explorer 找到 通过电子邮件搜索示例查询用户。这是我正在尝试实现的功能。

将 Startup.cs 代码复制到 Controller 中会导致解决方案失败并返回以下错误页面: ErrorPage1

ErrorPage2

最佳答案

抱歉,我第一次问错了你的问题。因此,基本上,您在调用 services.AddWebAppCallsProtectedWebApi() 时注册您的 ITokenAcquisition。尝试修改您的Homecontroller。删除这一行:

var tokenAcquisition = this.HttpContext.RequestServices
                .GetRequiredService<ITokenAcquisition>() as ITokenAcquisition;

并使用此实例:_tokenAcquisition

关于c# - 使用依赖注入(inject)将 token 获取从startup.cs传递到HomeController.cs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63271434/

相关文章:

.net - 一个好的 gradle nunit 插件?

asp.net-mvc - ASP.NET Core TestServer 导致 Razor View 出现 HTTP 500

c# - 如何使用字符串列表作为列表框的数据源

c# - 在 sql server 上从 C# 运行查询

c# - 如果是 .NET Framework 的 .NET 库,如何在 OSX 中使用 GemBox.Spreadsheet

.net - 错误模板显示在其他控件之上,而本应隐藏它

c# - ASP.Core 中的 .NET 版本

.net - ASP.net : How to log from within CreateHostBuilder()?

c# - 反序列化具有相同元素名称但不同属性的 Xml

c# - 如何在 C# 中允许 Class Property 具有多种/灵活类型?