После долгих ночей поиска в Google, мой вопрос здесь - последняя решительная попытка решить проблему. Я читаю книгу Адама Фримена под названием Pro Asp.Net Core Mvc 2. Я попал в очень интересную главу, где автор создает систему входа / регистрации пользователя с использованием 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 перенаправляет пользователя на страницу входа. Я прочитал несколько постов, касающихся некоторых пользовательских настроек печенья и реализации IPrincipal, чтобы решить эту проблему. Вопрос в том, как это возможно, чтобы у автора это работало без дополнительной настройки.
Мои знания по-прежнему являются базовыми, поэтому я стараюсь пока упростить их, пока не пойму основные понятия.
Любая помощь приветствуется.
Спасибо, Жолт.