При использовании Asp.Net Core Identity в MVC атрибут Authorize восстанавливается после входа в систему после успешного входа. - PullRequest
0 голосов
/ 27 июня 2018

После долгих ночей поиска в 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, чтобы решить эту проблему. Вопрос в том, как это возможно, чтобы у автора это работало без дополнительной настройки. Мои знания по-прежнему являются базовыми, поэтому я стараюсь пока упростить их, пока не пойму основные понятия. Любая помощь приветствуется. Спасибо, Жолт.

1 Ответ

0 голосов
/ 28 июня 2018

Порядок регистрации промежуточного программного обеспечения имеет значение. Переместите app.UseAuthentication() вызов до app.UseMvc(...).

Обычно все, что происходит до ответа, возвращаемого (например, аутентификация), должно происходить до регистрации промежуточного программного обеспечения MVC.

...