在 Asp.Net Core 2 中将 SignInManager 和 AspNetUserManager 注入中间件
Posted
技术标签:
【中文标题】在 Asp.Net Core 2 中将 SignInManager 和 AspNetUserManager 注入中间件【英文标题】:Injecting SignInManager and AspNetUserManager to Middleware in Asp.Net Core 2 【发布时间】:2018-08-27 19:34:04 【问题描述】:我正在尝试将SignInManager<ApplicationUser>
和AspNetUserManager<ApplicationUser>
注入到我的WebApi 的刷新令牌中间件中。只是为了不使用身份,所以我的 ApplicationUser
类是
public class ApplicationUser : IdentityUser<int>, IEntity
在我的中间件构造函数中我有;
private readonly AuthService _service;
public TokenProviderMiddleware(
RequestDelegate next,
Func<IMyDataContext> context,
SignInManager<ApplicationUser> signInManager,
AspNetUserManager<ApplicationUser> userManager)
_next = next;
_serializerSettings = new JsonSerializerSettings
Formatting = Formatting.Indented
;
_service = new AuthService(context, signInManager, userManager);
在我的 Startup.cs 中有以下内容;
public void ConfigureServices(IServiceCollection services)
services.AddDbContext<MyDataContext>(
options => options.UseSqlServer(DbGlobals.DevDatabase));
services.AddTransient<IMyDataContext, MyDataContext>();
services.AddTransient<Func<IMyDataContext>>(provider => () => provider.GetService<IMyDataContext>());
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<BemfeitoDataContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
);
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
options.Issuer = JwtSettings.Issuer;
options.Audience = JwtSettings.Audience;
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
);
var tokenValidationParameters = new TokenValidationParameters
ValidateIssuer = true,
ValidIssuer = JwtSettings.Issuer,
ValidateAudience = true,
ValidAudience = JwtSettings.Audience,
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
;
services.AddAuthentication(options =>
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(configureOptions =>
configureOptions.ClaimsIssuer = JwtSettings.Issuer;
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.Events = new JwtBearerEvents
OnAuthenticationFailed = context =>
Console.WriteLine("OnAuthenticationFailed: " +
context.Exception.Message);
return Task.CompletedTask;
,
OnTokenValidated = context =>
Console.WriteLine("OnTokenValidated: " +
context.SecurityToken);
return Task.CompletedTask;
;
);
// api user claim policy
services.AddAuthorization(options =>
options.AddPolicy("ApiUser", policy => policy.RequireClaim(JwtClaimIdentifiers.Rol, JwtClaims.ApiAccess));
);
services.AddMvc();
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseHttpErrorHandlerMiddleware();
app.UseTokenProviderMiddleware();
app.UseRefreshTokenProviderMiddleware();
app.UseAuthentication();
app.UseMvc();
当我运行它时,我收到以下错误;
InvalidOperationException:无法从根提供商解析范围服务“Microsoft.AspNetCore.Identity.SignInManager`1[ApplicationUser]”。
我已尝试添加以下瞬态;
services.AddTransient<IUserStore<ApplicationUser>, UserStore<ApplicationUser, ApplicationRole, MyDataContext, int>>();
services.AddTransient<SignInManager<ApplicationUser>>();
services.AddTransient<UserManager<ApplicationUser>>();
但是我似乎陷入了注入依赖的兔子洞,因为它现在也请求注入 UserStore?有没有更简单的方法可以注入这些服务?
【问题讨论】:
您无法选择UserManager<ApplicationUser>
和SignInManager<ApplicationUser>
是否注册了不同的生命周期。它作为 Startup.cs 中 AddIdentity
调用的一部分自动发生。控制器还具有用户管理器 AspNetUserManager<ApplicationUser>
。你的意思是写UserManager<ApplicationUser>
?
好的,请问如何在中间访问它们?是的,对不起错字,我的意思是 UserManager
您的中间件应该有一个带有此签名public async Task Invoke(HttpContext context)
的调用方法。您可以使用HttpContext
的RequestServices.GetService
从 IoC 获取服务。
我确实认为这是一种访问方式,正如你所看到的,我将它传递给我的工厂,即AuthService(context, signInManager, userManager)
,所以我想我必须在构造函数中将上下文设置为它的注入和在Invoke
方法中创建实例。
嘿@MatthewFlynn 你找到解决这个问题的方法了吗?我也想在中间件中使用 UserManager,但不能注入它
【参考方案1】:
可能有一种更简单的方法可以让您在中间件中访问这些服务。考虑以下方法,而不是尝试将 SignInManager signInManager 和 AspNetUserManager userManager 直接注入中间件,而是注入 Microsoft.AspNetCore.Http.IHttpContextAccessor _httpContextAccessor
然后您可以使用 _httpContextAccessor 访问 signInManager 和 userManager 服务,如下所示:
var userManager = _httpContextAccessor.HttpContext.RequestServices.GetService<AspNetUserManager<ApplicationUser>>();
var signInManager = _httpContextAccessor.HttpContext.RequestServices.GetService<SignInManager<ApplicationUser>>();
还要确保您的中间件类具有以下 using 语句:
using Microsoft.Extensions.DependencyInjection;
【讨论】:
以上是关于在 Asp.Net Core 2 中将 SignInManager 和 AspNetUserManager 注入中间件的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ASP .NET Core 2.1 中将登录页面设为默认路由?
在 ASP.NET Core 2.1 中将 json 数据列表传递给 HttpPost 控制器
在 ASP.NET Core 2.0 中将 DataTable 转换为 IEnumerable<T>
ASP.NET 4.5 在 ASP.NET Core 2.0 应用程序下的 Azure Web App 中将 502.5 作为虚拟应用程序抛出