Пользователь не аутентифицирован после успешного входа - PullRequest
3 голосов
/ 26 июня 2019

Я создал приложение ASP.NET MVC с автоматически сгенерированным шаблоном логина / пароля по умолчанию из Visual Studio.

У меня есть некоторые действия [Авторизовать], которые правильно перенаправляют меня в форму входа, если яне вошел в систему. Когда я пытаюсь войти в систему с неправильным паролем, я получаю сообщение об ошибке, как и ожидалось.Затем, когда я пытаюсь ввести правильное имя пользователя и пароль, я не получаю никакой ошибки, но все равно не могу получить доступ к действию [Авторизовать].Приложение постоянно перенаправляет меня в форму входа в систему, потому что Return_url - это мое действие [Authorize].Я добавил отображение User.Identity.Name, и оно всегда пустое.

Сначала я изменил Login.cshtml следующим образом:

@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <div style="text-align:center; margin-top:10px">
        <h3>Log In</h3>
    </div>
    <hr />
    <div style="margin-left:10px">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    </div>
    <div style="margin-left:50px">
        <div class="form-group">
            @Html.LabelFor(m => m.User, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.User, new { placeholder = "Username", @class = "form-control" })
                @Html.ValidationMessageFor(m => m.User, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.Password, new { placeholder = "Password", @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <div class="checkbox">
                    @Html.CheckBoxFor(m => m.RememberMe)
                    @Html.LabelFor(m => m.RememberMe)
                </div>
            </div>
        </div>
    </div>
    <div style="margin-left:25px">
        <div class="form-group">
            <div class="col-md-12">
                <input type="submit" value="Connect" class="btn btn-primary btn-lg btn-block" />
            </div>
        </div>
    </div>
}

И я также изменилМодель LoginViewModel выглядит следующим образом:

public class LoginViewModel
{
    [Required]
    [Display(Name = "User")]
    [DataType(DataType.Text)]
    public string User { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Display(Name = "Remember me?")]
    public bool RememberMe { get; set; }
}

После этого я изменил свой логин ActionResult, вызванный по запросу HttpPOST:

// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    var result = SignInManager.CustomPasswordSignIn(model.User, model.Password, model.RememberMe, shouldLockout: false);
    switch (result)
    {
        case CustomSignInStatus.Success:
            return RedirectToLocal(returnUrl);
        case CustomSignInStatus.Admin:
            return RedirectToLocal(returnUrl);
        case CustomSignInStatus.LockedOut:
            return View("Lockout");
        case CustomSignInStatus.RequiresVerification:
            return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, model.RememberMe });
        case CustomSignInStatus.Satellite_fail:
            ModelState.AddModelError("", "Satellite failed.");
            return View(model);
        case CustomSignInStatus.Failure:
        default:
            ModelState.AddModelError("", "Incorrect login or password.");
            return View(model);
    }

Поскольку мне требовалось больше ситуаций входа (Success, Admin, LockedOut, Требуется проверка), Satellite_fail, Failure) Я создал CustomSignInStatus:

public enum CustomSignInStatus
    {
        //
        // Summary:
        //     Sign in was successful
        Success = 0,
        //
        // Summary:
        //     User is locked out
        LockedOut = 1,
        //
        // Summary:
        //     Sign in requires addition verification (i.e. two factor)
        RequiresVerification = 2,
        //
        // Summary:
        //     Sign in failed
        Failure = 3,
        //
        // Summary:
        //     Satellite sign in failed
        Satellite_fail = 4,
        //
        // Summary:
        //     Admin sign in
        Admin = 5
    }

Затем мне пришлось реализовать свой собственный CustomPasswordSignIn, чтобы использовать мой CustomSignInStatus следующим образом:

public CustomSignInStatus CustomPasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout)
        {
            string hashpwd = Tools.HashData(password);

            if (userName == "admin" && hashpwd == ConfigurationManager.AppSettings["ADMIN"]) return CustomSignInStatus.Admin;

            using (IDal dal = new Dal())
            {
                int sat = dal.GetSatellite();

                if (sat == -1) return CustomSignInStatus.Satellite_fail;

                if (dal.CheckLogs(userName, hashpwd, sat)) return CustomSignInStatus.Success;
            }

            return CustomSignInStatus.Failure;
        }

Этот метод хэширует входной пароль,проверяет, является ли пользователь администратором, затем пытается проверить Satellite и логин / пароль пары.

В этот момент кажется, что аутентификация работает, но сеанс не создается, пользователь не аутентифицирован ипоэтому не имеет доступа к действиям [Authorize].Я думаю, что мне нужно где-то добавить создание сеанса, но я не могу найти то, чего не хватает в моем коде.Как я могу аутентифицировать своего пользователя после успешного входа?

Ответы [ 2 ]

1 голос
/ 27 июня 2019

Я узнал, как решить мою проблему:

В AccountController, при действии входа в систему и внутри переключателя из результата вызова SignInManager.CustomPasswordSignIn я отредактировал такие случаи:

case CustomSignInStatus.Admin:
    adm = true;
    goto case CustomSignInStatus.Success;
case CustomSignInStatus.Success:

    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.Name, model.User)
    };
    if (adm) claims.Add(new Claim(ClaimTypes.Role, "Administrator"));
    var id = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);

    var ctx = Request.GetOwinContext();
    var authenticationManager = ctx.Authentication;
    authenticationManager.SignIn(id);

    return RedirectToLocal(returnUrl);

Теперь мой пользователь правильно идентифицирован и имеет доступ к действиям [Авторизовать].

0 голосов
/ 26 июня 2019

, если вы используете FormsAuthentication, тогда вам нужно использовать SetAuthCookie в FormsAuthentication, когда пользователь проверяется так:

case CustomSignInStatus.Success:
FormsAuthentication.SetAuthCookie(model.User, model.RememberMe);
return RedirectToLocal(returnUrl);
...