如何在AspNet.Core 2.1中通过依赖注入添加UserManager?

6

我创建了一个使用Identity Server 4进行Bearer Token身份验证的Asp.Net Core 2.1 Web Api。我有两个db上下文,一个用于身份验证,一个用于我的自定义应用程序的数据访问。我想在我的Web Api中使用UserManager和UserStore,并在我的控制器中使用依赖注入。

问题是,一旦我添加了DI的“相关”代码,我的控制器方法就会抛出302错误,并尝试将我重定向到登录URL。就像我的Bearer身份验证被覆盖一样。以下是我的Startup.cs的代码。你有什么想法应该如何解决吗?

   public void ConfigureServices(IServiceCollection services)
   {

        string connectionString = Configuration.GetConnectionString("DefaultConnection");
        var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

        services.AddDbContext<CustomContext>(options =>
            options.UseSqlServer(connectionString));

        // start of the stuff that should add the usermanager and userstore
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connectionString));


        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
        // end of the stuff

        services.AddMvcCore()
            .AddAuthorization()
            .AddJsonFormatters();

        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "http://authenticate.com";
                options.RequireHttpsMetadata = false;

                options.ApiName = "api1";
            });

        services.AddCors(options =>
        {
            // this defines a CORS policy called "default"
            options.AddPolicy("default", policy =>
            {
                policy.AllowAnyOrigin()
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials();
            });
        });


    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseAuthentication();
        app.UseCors("default");
        app.UseMvc();
    }

控制器长这样:
public class PlayerController : BaseApiController
{
    private readonly UserManager<ApplicationUser> userManager;

    public PlayerController(UserManager<ApplicationUser> _userManager)
    {
        userManager = _userManager;
    }
    .....
 }

使用如下的BaseApiController:

[Route("api/[controller]")]
[Authorize]
public class BaseApiController : Controller
{
    ...
}

2
除了在控制器构造函数中添加 UserManager<T> 之外,您无需进行任何特殊操作。当您使用 Identity 时,其他所有内容都已经就位。难道您正在使用 MVC 控制器,而您的错误视图/操作需要身份验证吗?! - Tseng
1
请记住,在CORS注册之后进行身份验证是建议的。您不希望未登录的用户遇到CORS错误。 - Tseng
1
@Tseng 是的,完全正确,这就是我之前已经说过的。如果我删除那段据称添加 DI 的代码 services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders();一切都会按照预期进行,如果我的身份验证不再有效,我会得到 401 错误。加入“DI 代码”会导致我得到一个 302 重定向,这意味着它正在覆盖我的 Bearer 身份验证。我想添加 UserManager,而不创建另一层身份验证。 - littleowlnest
1
IdentityServer和您的WebAPI不在同一个应用程序中,对吗?如果它们是单独的应用程序,则您的WebApi项目中不需要ASP.NET Core Identity,只需要AddIdentityServerAuthentication调用。如果它们是同一个应用程序(不建议这样做),则需要按照文档将ASP.NET Core Identity与IdSrv4集成。 - Tseng
1
如果您的API服务器被黑客攻击,您将面临更高的安全风险,攻击者还可以访问您的身份数据库。此外,如果您更改安全设置(更强的密码策略),则不会应用于资源应用程序(使用核心身份验证和授权其资源的WebApi应用程序),因为密码和其他内容也可以从中更改。即,如果您从第二个应用程序更改密码,则可能使用过时(且不太安全)的设置。实际上,只有核心身份验证服务器应该拥有所有权并更改此数据的权限,而没有其他应用程序。这是糟糕的应用程序设计。 - Tseng
显示剩余11条评论
1个回答

3

services.AddIdentity<TUser>() 添加了一个“不必要”的身份验证配置,因为您已经从 services.AddAuthentication("Bearer").AddIdentityServerAuthentication() 配置中拥有了一个令牌方案。请查看下面的代码以获取 AddIdentity()。请注意,还添加了多少个方案(包括 cookie 方案)。

public static IdentityBuilder AddIdentity<TUser, TRole>(
        this IServiceCollection services,
        Action<IdentityOptions> setupAction)
        where TUser : class
        where TRole : class
    {
        // Services used by identity
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
            options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
            options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
        })
        .AddCookie(IdentityConstants.ApplicationScheme, o =>
        {
            o.LoginPath = new PathString("/Account/Login");
            o.Events = new CookieAuthenticationEvents
            {
                OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
            };
        })
        .AddCookie(IdentityConstants.ExternalScheme, o =>
        {
            o.Cookie.Name = IdentityConstants.ExternalScheme;
            o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
        })
        .AddCookie(IdentityConstants.TwoFactorRememberMeScheme, o =>
        {
            o.Cookie.Name = IdentityConstants.TwoFactorRememberMeScheme;
            o.Events = new CookieAuthenticationEvents
            {
                OnValidatePrincipal = SecurityStampValidator.ValidateAsync<ITwoFactorSecurityStampValidator>
            };
        })
        .AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
        {
            o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
            o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
        });

        // cut for brevity

        return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
    }

你不需要那个。你需要的是:

services.AddIdentityCore<TUser>()

这不会添加其他认证配置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接