C# ASP.NET核心Web API,如何在启动类中访问HttpContext
我正在尝试访问C# ASP.NET核心Web API,如何在启动类中访问HttpContext,c#,api,asp.net-core,.net-core,C#,Api,Asp.net Core,.net Core,我正在尝试访问HttpContext以获取RemoteIpAddress和用户代理,但在Startup.cs内 public class Startup { public Startup(IConfiguration configuration, IHttpContextAccessor httpContextAccessor) { Configuration = configuration;
HttpContext
以获取RemoteIpAddress
和用户代理
,但在Startup.cs内
public class Startup
{
public Startup(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
{
Configuration = configuration;
_httpContextAccessor = httpContextAccessor;
}
public IConfiguration Configuration { get; }
public IHttpContextAccessor _httpContextAccessor { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
IdentityModelEventSource.ShowPII = true;
var key = Encoding.ASCII.GetBytes(Configuration.GetValue<string>("claveEncriptacion"));
var ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
var userAgent = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
//x.Audience = ip + "-" + userAgent;
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = true
};
});
根据,在使用通用主机(IHostBuilder)时,只能将以下服务类型注入到启动
构造函数中:
因此,无法将IHttpContextAccessor
注入启动
构造函数
但是,您可以在Startup
类的ConfigureServices
方法中获得DI解析服务,如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IYourService, YourService>();
// Build an intermediate service provider
var serviceProvider = services.BuildServiceProvider();
// Resolve the services from the service provider
var yourService = serviceProvider.GetService<IYourService>();
}
public class YourCustomMiddleMiddleware
{
private readonly RequestDelegate _requestDelegate;
public YourCustomMiddleMiddleware(RequestDelegate requestDelegate)
{
_requestDelegate = requestDelegate;
}
public async Task Invoke(HttpContext context)
{
// Your HttpContext related task is in here.
await _requestDelegate(context);
}
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware(typeof(YourCustomMiddleMiddleware));
}
然后在启动
类的配置
方法中,如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IYourService, YourService>();
// Build an intermediate service provider
var serviceProvider = services.BuildServiceProvider();
// Resolve the services from the service provider
var yourService = serviceProvider.GetService<IYourService>();
}
public class YourCustomMiddleMiddleware
{
private readonly RequestDelegate _requestDelegate;
public YourCustomMiddleMiddleware(RequestDelegate requestDelegate)
{
_requestDelegate = requestDelegate;
}
public async Task Invoke(HttpContext context)
{
// Your HttpContext related task is in here.
await _requestDelegate(context);
}
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware(typeof(YourCustomMiddleMiddleware));
}
我终于找到了一个可能的解决方案,使用
中间件
验证令牌。
我创建了一个类ValidationHandler
,这个类可以使用HttpContext
public class ValidationRequirement : IAuthorizationRequirement
{
public string Issuer { get; }
public string Scope { get; }
public HasScopeRequirement(string scope, string issuer)
{
Scope = scope ?? throw new ArgumentNullException(nameof(scope));
Issuer = issuer ?? throw new ArgumentNullException(nameof(issuer));
}
}
public class ValidationHandler : AuthorizationHandler<ValidationRequirement>
{
IHttpContextAccessor _httpContextAccessor;
public HasScopeHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
{
var ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
var userAgent = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
//context.Succeed(requirement);
return Task.CompletedTask;
}
}
谢谢你,维德加加。我想投票,但我有一个新帐户。你的回答对我的项目有帮助。我来自f#land,因此我将为任何需要此解决方案的FSharper提供我的实现
type HasScopeHandler() =
inherit AuthorizationHandler<HasScopeRequirement>()
override __.HandleRequirementAsync(context, requirement) =
let scopeClaimFromIssuer = Predicate<Claim>(fun (c: Claim) -> c.Type = "scope" && c.Issuer = requirement.Issuer)
let userDoesNotHaveScopeClaim = not (context.User.HasClaim(scopeClaimFromIssuer))
let isRequiredScope s = (s = requirement.Scope)
let claimOrNull = context.User.FindFirst(scopeClaimFromIssuer)
if (userDoesNotHaveScopeClaim) then
Task.CompletedTask
else
match claimOrNull with
| null -> Task.CompletedTask
| claim ->
let scopes = claim.Value.Split(' ')
let hasRequiredScope = scopes.Any(fun s -> isRequiredScope s)
if (hasRequiredScope) then
context.Succeed(requirement)
Task.CompletedTask
else
Task.CompletedTask
type HasScopeHandler()=
继承AuthorizationHandler()
重写_uu.HandleRequirementAsync(上下文、需求)=
让scopeClaimFromIssuer=谓词(fun(c:Claim)->c.Type=“scope”&&c.Issuer=requirement.Issuer)
让userDoesNotHaveScopeClaim=not(context.User.HasClaim(scopeClaimFromIssuer))
让isRequiredScope s=(s=requirement.Scope)
让claimOrNull=context.User.FindFirst(scopeClaimFromIssuer)
如果(用户未声明)则
Task.CompletedTask
其他的
将claimOrNull与
|null->Task.CompletedTask
|索赔->
让scopes=claim.Value.Split(“”)
让hasRequiredScope=scopes.Any(乐趣s->isRequiredScope s)
如果(需要示波器),则
成功(要求)
Task.CompletedTask
其他的
Task.CompletedTask
您想要实现什么目标?您无法在启动时访问HttpContext
,因为startup.cs中没有发出任何请求。我需要获取RemoteIpAddress和User agent启动时您试图获取的IP和User agent是什么?它们仅在请求IP和用户代理添加x时可用。访问群体,因为令牌的访问群体是dinamicI。我已经测试了您的代码,并且我有空引用的_httpContextAccessorOkay!明白原因了!我将很快更新答案,解释解决问题的原因和方法!请告诉我您想从HttpContext获得什么。我需要创建一个令牌,然后仅从创建该令牌的同一浏览器和pc调用该令牌。为了实现这一区别,我使用了IP和用户代理。但是我需要在ConfigureServices中使用它,因为令牌是经过验证的inside@vidgarga您应该能够从自定义中间件执行完全相同的操作。在Startup
类的Configure
方法中注册中间件。