c# - ASP.NET Core 2.0 Identity : SignInManager. IsSignedIn(User) 登录后返回 false

标签 c# asp.net-core asp.net-identity asp.net-core-2.0

我遇到一个问题,在创建用户并登录 SignInManager.IsSignedIn(User) 方法后返回 false

我正在使用 SPA Angular CLI 模板的新 2.0.0 预览版,我已经根据我在文档中阅读的内容添加了所有身份配置,并使用其他一些 Visual Studio 模板作为指南.

下面是我的 Startup 类。

public class Startup
{
    public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
    {
        Configuration = configuration;
        HostingEnvironment = hostingEnvironment;

        //configration
        MyAppConfig.ConnectionString = Configuration.GetConnectionString("DefaultConnection");
        MyAppConfig.Secure = Configuration.GetValue<bool>("App:Secure", true);
    }

    public IConfiguration Configuration { get; }
    private IHostingEnvironment HostingEnvironment { get; set; }
    public IContainer ApplicationContainer { get; private set; }

    private const string EmailConfirmationTokenProviderName = "ConfirmEmail";

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });


        IDataProtectionBuilder dataProtectionBuilder = services.AddDataProtection()
            .SetApplicationName("MyApp");

        //data protection
        if (HostingEnvironment.IsDevelopment())
        {
            //for development, do default (intentionally left blank for now)
        }
        else
        {
            //for deployments, protect certificate and persist to azure storage
            //this will allow swapping of web app slots 
            dataProtectionBuilder
                .ProtectKeysWithCertificate("")
                .PersistKeysToAzureBlobStorage(new Uri(""));
        }


        //ssl
        if (!HostingEnvironment.IsDevelopment())
        {
            services.Configure<MvcOptions>(options =>
            {
                options.Filters.Add(new RequireHttpsAttribute());
            });
        }

        var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();

        //anti-forgery, add to all controllers
        services.AddMvc(options => {
            options.Filters.Add(new ValidateAntiForgeryTokenAttribute());
            options.Filters.Add(new AuthorizeFilter(policy));
        });

        services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");

        services.AddDbContext<AppDbContext>(options =>
            options.UseSqlServer(MyAppConfig.ConnectionString));

        //identity
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<AppDbContext>()
            .AddDefaultTokenProviders()
            .AddTokenProvider<ConfirmEmailDataProtectorTokenProvider<ApplicationUser>>(EmailConfirmationTokenProviderName); ;

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings
            options.Password.RequireDigit = true;
            options.Password.RequiredLength = 8;
            options.Password.RequireNonAlphanumeric = true;
            options.Password.RequireUppercase = true;
            options.Password.RequireLowercase = false;
            options.Password.RequiredUniqueChars = 4;

            // Lockout settings
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
            options.Lockout.MaxFailedAccessAttempts = 5;
            options.Lockout.AllowedForNewUsers = true;

            // User settings
            options.User.RequireUniqueEmail = true;

            // SignIn settings
            options.SignIn.RequireConfirmedEmail = true;
            options.SignIn.RequireConfirmedPhoneNumber = false;

            options.Tokens.EmailConfirmationTokenProvider = EmailConfirmationTokenProviderName;
        });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.Cookie.Expiration = TimeSpan.FromHours(1);
            options.SlidingExpiration = true;
        });

        services.Configure<ConfirmEmailDataProtectionTokenProviderOptions>(options =>
        {
            options.TokenLifespan = TimeSpan.FromDays(180);
        });


        //autofac
        var builder = new ContainerBuilder();

        builder.Populate(services);
        builder.RegisterType<AccountService>().As<IAccountService>();
        builder.RegisterType<EmailService>().As<IEmailService>();

        this.ApplicationContainer = builder.Build();

        // Create the IServiceProvider based on the container.
        return new AutofacServiceProvider(this.ApplicationContainer);

    }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseSpaStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");
        });

        //send anti-forgery cookie with initial SPA page
        //must be before UseSpa() call
        app.Use(next => context =>
        {
            if (
                string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase))
            {
                // We can send the request token as a JavaScript-readable cookie, and Angular will use it by default.
                var tokens = antiforgery.GetAndStoreTokens(context);
                context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
                    new CookieOptions() { HttpOnly = false });
            }

            return next(context);
        });

        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
                //spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
            }
        });

        //auth & identity
        app.UseAuthentication();
    }

}

以下是我用来测试用户是否登录的步骤:

  1. 创建用户
  2. 验证电子邮件(然后让请求完成)
  3. 在返回成功的新 HTTP 请求中调用 SignInManager.PasswordSignInAsync()
  4. 让请求返回
  5. 验证 .AspNetCore.Identity.Application cookie 是否存在
  6. 启动另一个调用 SignInManager.IsSignedIn(User) 的 HTTP 请求并返回 false

我不确定问题可能是什么,因为我已经阅读了 https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?tabs=visual-studio%2Caspnetcore2x 上的文档。

最佳答案

您的中间件按照您在应用中声明的顺序执行。这是一个很棒的resource为了帮助您更好地理解,

enter image description here

当您最后调用身份验证时,这将是管道中完成的最后一件事:

app.UseAuthentication();

要解决此问题,只需将此行放在:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action=Index}/{id?}");
});

关于c# - ASP.NET Core 2.0 Identity : SignInManager. IsSignedIn(User) 登录后返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48465397/

相关文章:

c# - 使用 linq 过滤嵌套集合

c# - 如何确定 List<Object> 的对象?

asp.net-core - 为什么 Visual Studio 2019 16.9.5 中 .NET Core 3.1 和 .NET 5 的 Scaffolding Identity 失败?

javascript - WEB API - 如何使用身份向用户中的自定义属性添加值

asp.net - 使用 Asp.Net Identity 2.0 管理 2 个级别的身份验证

c# - 使用 Swagger 的特定状态代码的响应模型

c# - SomeDelegate.Invoke 究竟在哪里实现以及它是如何 "wired"到委托(delegate)类

c# - 如何在asp.net core中添加多个身份和多个角色

asp.net-core - asp.net core 中的 ViewEngineCollection 替代品?

docker - 响应状态码不表示成功 : 401 (Unauthorized) - Azure Devops Feed ASP. NET Core 3.1 Docker Build