在MVC中使用Asp.Net Core Identity,成功登录后,Authorize属性会重新启动到登录页面

时间:2018-06-26 21:26:51

标签: asp.net asp.net-core-mvc identity authorize

经过漫长的谷歌搜索之夜,在这里问我的问题是解决问题的最后一次激烈尝试。我正在阅读亚当·弗里曼(Adam Freeman)的一本书,名为Pro Asp.Net Core Mvc2。我读到了非常有趣的一章,其中的作者使用Identity API创建了用户登录/注册系统。该示例非常简单,但是我一直很困惑,而且由于我没有看到任何使用此方法的帖子,因此我决定在此处创建一个问题。因此,在本书中,这是从IdentityUser继承的用户模型类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;

namespace supafood.Models
{
public class AppUser:IdentityUser
{
    //basic identity instalation

}
    }

然后这是一个附加的userviewmodel类,该模型传递给登录表单

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;

namespace supafood.Models
{
    public class CreateModel
    {
    [Required]
    public string Name { get; set; }

    [Required]
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
    }

    public class LoginModel
    {
        [Required]
        [UIHint("email")]
        public string Email { get; set; }

        [Required]
        [UIHint("password")]
        public string Password { get; set; }

        public string returnUrl { get; set; }
    }
}

起始页面的控制器,将未经授权的用户重定向到登录页面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;

namespace supafood.Controllers
{
    public class HomeController:Controller
    {
    [Authorize]
    public ViewResult Index() =>
        View(new Dictionary<string, object>
        {
            ["Placeholder"] = "Placeholder"
        });
    }
}

“登录视图”页面:

@model LoginModel

<div class="bg-primary mm-1 p-1 text-white"><h4>Log in</h4></div>

<div class="text-danger" asp-validation-summary="All"></div>
<h3>@ViewBag.returnUrl</h3> 
<p>@ViewData["mess"]</p> 

<form asp-action="Login" method="post">

<input type="hidden" asp-for="returnUrl" value="@ViewBag.returnUrl" />

<div class="form-group">
    <label asp-for="Email"></label>
    <input asp-for="Email" class="form-control" />
</div>
<div class="form-group">
    <label asp-for="Password"></label>
    <input asp-for="Password" class="form-control" />
</div>
<button type="submit" class="btn btn-sm btn-primary">Login</button>
</form>

然后由AccountController处理登录尝试,将重定向返回到请求的页面。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using supafood.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;

namespace supafood.Controllers
{

[Authorize]
public class AccountController : Controller
{

    private UserManager<AppUser> userMan;
    private SignInManager<AppUser> signinMan;

    public AccountController(UserManager<AppUser> UserM, 
  SignInManager<AppUser> SignM)
    {
        userMan = UserM;
        signinMan = SignM;
    }

    [AllowAnonymous]
    public IActionResult Login(string returnUrl)
    {

        ViewBag.returnUrl = returnUrl;
        return View();
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginModel details)
    {
        if (ModelState.IsValid)
        {
            AppUser user =await  userMan.FindByEmailAsync(details.Email);
            ViewData["name"] = user.UserName;
            if (user != null)
            {
                await signinMan.SignOutAsync();
                Microsoft.AspNetCore.Identity.SignInResult result = await 
signinMan.PasswordSignInAsync(user, details.Password, false, false);
                if (result.Succeeded)
                {


                    return Redirect(details.returnUrl);
                }

            }
            ModelState.AddModelError(nameof(LoginModel.Email), "Invalid user         
or password");
        }
        return View(details);

    }
}
}

启动类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using supafood.Models;
using supafood.Infrastructure;


namespace supafood
{
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IPasswordValidator<AppUser>, 
CustomPasswordValidator>();

        services.AddDbContext<AppIdentityDbContext>(options =>
            options.UseSqlServer(
                Configuration["Data:SupafoodConnection:ConnectionString"]));

        services.ConfigureApplicationCookie(opts => opts.LoginPath = 
"/Users/Login");

        services.AddIdentity<AppUser, IdentityRole>(opts =>
        {
            opts.User.RequireUniqueEmail = true;
            opts.User.AllowedUserNameCharacters="abcdefghijklmnopqrstuvwxyz";
            opts.Password.RequiredLength = 6;
            opts.Password.RequireNonAlphanumeric = false;
            opts.Password.RequireLowercase = false;
            opts.Password.RequireUppercase = false;
            opts.Password.RequireDigit = false;
        }
        )
            .AddEntityFrameworkStores<AppIdentityDbContext>()
            .AddDefaultTokenProviders();


        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)
    {
        app.UseStatusCodePages();
        app.UseStaticFiles();
        app.UseDeveloperExceptionPage();
        app.UseMvc(routes =>
        routes.MapRoute("default", " 
{controller=Home}/{action=Index}/{id?}"));
        app.UseAuthentication();
    }
}
}

问题在于,登录后,authorize属性会将“用户”弹回登录页面。我阅读了一些有关一些自定义cookie设置选项和IPrincipal实现的文章,以解决此问题。问题是,它可能如何在没有其他自定义的情况下为作者工作。 我的知识仍然很基础,因此在不了解核心概念之前,我尝试将其保持简单。 感谢您的帮助。 谢谢,兹索尔特。

1 个答案:

答案 0 :(得分:1)

中间件注册的顺序很重要。将app.UseAuthentication()呼叫移至app.UseMvc(...)之前。

通常,在返回响应之前 发生的任何事情(如身份验证)都应在注册MVC中间件之前进行。

相关问题