经过漫长的谷歌搜索之夜,在这里问我的问题是解决问题的最后一次激烈尝试。我正在阅读亚当·弗里曼(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实现的文章,以解决此问题。问题是,它可能如何在没有其他自定义的情况下为作者工作。 我的知识仍然很基础,因此在不了解核心概念之前,我尝试将其保持简单。 感谢您的帮助。 谢谢,兹索尔特。
答案 0 :(得分:1)
中间件注册的顺序很重要。将app.UseAuthentication()
呼叫移至app.UseMvc(...)
之前。
通常,在返回响应之前 发生的任何事情(如身份验证)都应在注册MVC中间件之前进行。