ASP.NET Core 2.0标识:SignInManager.IsSignedIn(User)在登录

时间:2018-01-26 16:22:57

标签: 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(),返回Success
  4. 让请求返回
  5. 验证.AspNetCore.Identity.Application cookie是否存在
  6. 发起另一个调用SignInManager.IsSignedIn(User)的HTTP请求,并返回false
  7. 我不确定问题可能是什么,因为我已阅读https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?tabs=visual-studio%2Caspnetcore2x上的文档

1 个答案:

答案 0 :(得分:5)

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

enter image description here

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

views/**

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

上方
app.UseAuthentication();