如何从.Net core 2.0中的HttpContext获取访问令牌

DaI*_*mTo 25 c# http .net-core asp.net-core

我正在尝试将.Net核心1.1的项目升级到.Net核心2.0,有很多重大变化.我目前遇到的一个问题HttpContext.Authentication是现在已经过时了.

我一直试图弄清楚如何获取当前请求的Access令牌.我需要调用另一个需要持有令牌的API.

旧方法.Net核心1.1

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

    return View();
}
Run Code Online (Sandbox Code Playgroud)

方法.Net核心2.0

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

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

    return View();
}
Run Code Online (Sandbox Code Playgroud)

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

我尝试注册它,但这也不起作用

public ConsoleController(IOptions<ServiceSettings> serviceSettings, HttpContext context) 
Run Code Online (Sandbox Code Playgroud)

在startup.cs中

services.TryAddSingleton<HttpContext, HttpContext>();
Run Code Online (Sandbox Code Playgroud)

更新:

返回null

var accessToken = await HttpContext.GetTokenAsync("access_token");  
Run Code Online (Sandbox Code Playgroud)

Startup.cs ConfigureServices

如果在初创公司中有什么东西我也不会感到惊讶,因为这里也有很多重大变化.

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;
            });
Run Code Online (Sandbox Code Playgroud)

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?}");
        });
Run Code Online (Sandbox Code Playgroud)

小智 36

.Net core 2.1 访问JWT bearer tocken

var accessToken = Request.Headers["Authorization"];
Run Code Online (Sandbox Code Playgroud)

  • @El Mac显然,我在Startup.ConfigureServices内部的AddOpenIdConnect方法中缺少options.SaveTokens = true。/sf/answers/3543619901/ (3认同)
  • 这不仅仅返回令牌。它还包括标头中的身份验证方案(“Bearer”),因此如果您只想要令牌,则必须提取它 (3认同)
  • “请求”从哪里来? (3认同)

小智 26

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

var _bearer_token = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", "");
Run Code Online (Sandbox Code Playgroud)

并记住你需要使用

using Microsoft.Net.Http.Headers;
Run Code Online (Sandbox Code Playgroud)

  • 非常脆。建议将其包装在 try...catch 下,但可选。 (3认同)
  • 请改用“HttpContext.GetTokenAsync(“access_token”)”。 (3认同)

DaI*_*mTo 18

它最终成为配置问题.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");
            });
Run Code Online (Sandbox Code Playgroud)

调节器

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

现在填充了访问令牌.

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

  • 它是!您的配置不正确,因为此答案明确表明。如果未填充HttpContext,将会得到NullReferenceException。这就是我所说的身份验证配置! (2认同)

use*_*994 8

与Azharuddin答案稍有不同

在启动方法中注册服务实例,例如

public void ConfigureServices(IServiceCollection services)
{

 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 ...
}
Run Code Online (Sandbox Code Playgroud)

并在您的控制器中注入依赖项

private IHttpContextAccessor _httpContextAccessor;
public ClientController(IHttpContextAccessor httpContextAccessor)
{
     _httpContextAccessor = httpContextAccessor;
}
Run Code Online (Sandbox Code Playgroud)

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

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

    ..........//Some other code
    return View();
}
Run Code Online (Sandbox Code Playgroud)


azh*_*ani 5

启动.cs:

 public void ConfigureServices(IServiceCollection services)
 {
    ...
     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    ...
 }
Run Code Online (Sandbox Code Playgroud)

控制器构造函数:

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();
}
Run Code Online (Sandbox Code Playgroud)

这应该有效