【问题标题】:How to get access token from HttpContext in .Net core 2.0如何从 .Net core 2.0 中的 HttpContext 获取访问令牌
【发布时间】:2018-09-20 23:12:35
【问题描述】:

我正在尝试将一个项目从 .Net core 1.1 升级到 .Net core 2.0,其中有很多重大变化。

我目前遇到的一个问题是HttpContext.Authentication 现在已过时。

我一直试图弄清楚如何获取当前请求的访问令牌。我需要调用另一个需要不记名令牌的 API。

旧方法 .Net core 1.1

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
    return View();
}

方法.Net core 2.0

这不起作用,因为上下文未注册。

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = await context.HttpContext.GetTokenAsync("access_token"); 
    return View();
}

无法解析类型“Microsoft.AspNetCore.Http.HttpContext”的服务

我试过注册了,但是也没用

public ConsoleController(IOptions<ServiceSettings> serviceSettings, HttpContext context) 

在startup.cs中

services.TryAddSingleton<HttpContext, HttpContext>();

更新:

这将返回 null

var accessToken = await HttpContext.GetTokenAsync("access_token");  

Startup.cs 配置服务

如果这是初创公司的事情,我不会感到惊讶,因为这里也有很多重大变化。

services.Configure<ServiceSettings>(Configuration.GetSection("ServiceSettings"));
//services.TryAddSingleton<HttpContext, HttpContext>();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddMvc();
services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect(options =>
        {
            options.Authority = "http://localhost:5000";
            options.ClientId = "testclient";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token";
            options.RequireHttpsMetadata = false;
            options.GetClaimsFromUserInfoEndpoint = true;
        });

Startup.cs 配置

loggerFactory.AddDebug();
if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseBrowserLink();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

【问题讨论】:

  • 您不必注册HttpContext。它已经在您的控制器类中可用,就像在 1.1 中一样。
  • @Brad 这就是我的想法,但我无法访问它,请描述你的意思。
  • 你的控制器是否继承自 Controller 类?
  • 如果 GetAccessToken() 返回 null 可能是您的身份验证配置存在问题。您是如何在 Startup 中配置身份验证的?
  • ClientUpdate 在同一个 ConsoleController 中,所以我不得不说是?

标签: c# http asp.net-core .net-core


【解决方案1】:

Startup.cs:

 public void ConfigureServices(IServiceCollection services)
 {
    ...
     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    ...
 }

控制器构造函数:

private IHttpContextAccessor _httpContextAccessor;
public ClientController(IHttpContextAccessor httpContextAccessor)
{
     _httpContextAccessor = httpContextAccessor;
}

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
    return View();
}

这应该可以工作

【讨论】:

  • 适用于我 var token = HttpContext.Request.Headers["Authorization"][0]; @user1672994 做了一个小错字授权应该是授权
【解决方案2】:

在Controller中,可以通过读取Request.Headers字典来获取token:

 var accessToken = Request.Headers["Authorization"];

在 HttpContext 不可用的其他类中,可以在注入服务集合后使用HttpContextAccessor 检索令牌( 与 Azharuddin 的回答略有不同)

在 Startup 方法中注册服务实例

public void ConfigureServices(IServiceCollection services)
{

 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 ...
}

然后像这样在你的控制器中注入依赖项

private IHttpContextAccessor _httpContextAccessor;
public ClientController(IHttpContextAccessor httpContextAccessor)
{
     _httpContextAccessor = httpContextAccessor;
}

并在您的操作中检索访问令牌,例如

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];

    ..........//Some other code
    return View();
}

【讨论】:

    【解决方案3】:

    如果您想要纯令牌,这可以在 .net core 3.1 中为您提供帮助

    var _bearer_token = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", "");
    

    记住你需要添加这个使用

    using Microsoft.Net.Http.Headers;
    

    【讨论】:

    • 非常清脆。建议使用 try...catch 包装,但可选。
    • 这很好用!
    【解决方案4】:

    .Net Core 2.1 访问 JWT 不记名令牌

    var accessToken = Request.Headers[HeaderNames.Authorization];
    

    【讨论】:

    • @El Mac 显然,我在 Startup.ConfigureServices 内的 AddOpenIdConnect 方法中缺少 options.SaveTokens = truestackoverflow.com/a/50623141/2632991
    • 这不仅仅返回令牌。它还包括来自标头(“Bearer”)的身份验证方案,因此如果您只想要令牌,则必须提取它
    • 有没有办法不对"Authorization" 字符串进行硬编码?该字符串是在某处定义为常量还是枚举?
    • Request 来自哪里?
    【解决方案5】:

    您需要指定外部架构来检索令牌。

    var accessToken = await HttpContext.GetTokenAsync(IdentityConstants.ExternalScheme, "access_token");
    

    【讨论】:

      【解决方案6】:

      非常感谢,这太完美了!

      我有这项工作,但有我们天蓝色的租户专用权限。只需将 ****** 替换为您的租户名称即可。

      options.Authority = "https://login.microsoftonline.com/******.onmicrosoft.com";
      

      您也可以使用租户 ID。只需在https://login.microsoftonline.com/ 之后插入您的租户 ID

      options.Authority = "https://login.microsoftonline.com/be0be093-****-****-****-5626e83beefc";
      

      【讨论】:

        【解决方案7】:

        它最终成为配置问题。 AddAuthentication 和 AddOpenIdConnect 之间需要有一个链接,以便它将 cookie 读入标头中。

        services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        
        services.AddAuthentication(options =>
                    {
                        options.DefaultScheme = "Cookies";
                        options.DefaultChallengeScheme = "oidc";
                    })
                    .AddCookie("Cookies")
                    .AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = "Cookies";
        
                        options.Authority = "http://localhost:5000";
                        options.RequireHttpsMetadata = false;
        
                        options.ClientId = "testclient";
                        options.ClientSecret = "secret";
                        options.ResponseType = "code id_token";
                        options.SaveTokens = true;
                        options.GetClaimsFromUserInfoEndpoint = true;
        
                        options.Scope.Add("testapi");
                        options.Scope.Add("offline_access");
                    });
        

        控制器

            [Authorize]
            public async Task<IActionResult> Index()
            {
                var accessToken = await HttpContext.GetTokenAsync("access_token");
                return View();
            }
        

        现在已填充访问令牌。

        注意:我最终将它从这个项目中挖掘出来 Startup.cs

        【讨论】:

        • 您的控制器中不需要IHttpContextAccessor。它已经作为 HttpContext 属性存在。
        • 原来如此!您的配置不正确,因为这个答案清楚地表明了这一点。如果没有填充HttpContext,您将获得NullReferenceException。这就是我所说的身份验证配置!
        猜你喜欢
        • 1970-01-01
        • 2019-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-17
        • 1970-01-01
        • 2018-03-01
        • 1970-01-01
        相关资源
        最近更新 更多