Как постоянно обновлять переменные сессии в ASP.NET MVC - PullRequest
0 голосов
/ 05 июня 2018

После входа в систему я сохраняю некоторую информацию о пользователе в Session[""] vars.

 public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            try
            {
                var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);

                switch (result)
                {
                    case SignInStatus.Success:
                        var user = User.Identity;
                        try
                        {
                            ApplicationDbContext context = new ApplicationDbContext();

                            var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

                            string userId = UserManager.FindByName(model.UserName)?.Id;

                            var s = UserManager.GetRoles(userId);

                            var u = db.UsersViews.First(x => x.Id == userId);

                            Session["UserFullName"] = u.LastName + " " + u.FirstName.Substring(0, 1) + ". " + u.MiddleName.Substring(0, 1) + ".";
                            Session["UserRole"] =  u.RoleName;

                            return RedirectToAction("Index", "Home");
                        }
                        catch (Exception ex)
                        {
                            return View("Lockout");
                        }
                    case SignInStatus.LockedOut:
                        return View("Lockout");
                    case SignInStatus.RequiresVerification:
                        return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                    case SignInStatus.Failure:
                    default:
                        ModelState.AddModelError("", "Invalid login attempt.");
                        return View(model);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

Позже я использую ее как

@using Microsoft.AspNet.Identity

@if (Request.IsAuthenticated)
{
    using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
    {
        @Html.AntiForgeryToken()
        <div class="form-inline my-2 my-lg-0 " style="margin-left:2em; margin-right:0em;">
            <label class="form-control-sm mr-sm-2">@Session["UserFullName"] (@Session["UserRole"]) </label>
            <a href="javascript:document.getElementById('logoutForm').submit()" class="btn btn-outline-primary btn-sm my-2 my-sm-0">Выход</a>
        </div>
    }
}
else
{
    <form class="navbar-right">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item">
                <a id="loginLink" href="@Url.Content("~/Account/Login")" class="nav-link"><span class="glyphicon glyphicon-log-in"></span> Вход</a>
            </li>
        </ul>
    </form>
}

Но после завершения сеанса значения для отображения не отображаются.

Итак, мой вопрос, как сохранить обновленные переменные сессии без увеличения времени ожидания?

Спасибо!

1 Ответ

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

Я нашел ответ здесь ASP.NET MVC - Установить пользовательский IIdentity или IPrincipal

Но я немного изменил этот подход.

Вот мой рабочий код.

Создать несколько классов IPrincipal

 interface ICustomPrincipal : IPrincipal
    {
        string Id { get; set; }

        string FirstName { get; set; }
        string LastName { get; set; }
        string MiddleName { get; set; }

        string RoleName { get; set; }
    }

 public class CustomPrincipal : ICustomPrincipal
    {
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string MiddleName { get; set; }
        public string RoleName { get; set; }

        private string[] _roles; // Keep here English name of roles that ypu will use for Controller    [Authorize(Roles = "Administrator, Guest")]

        public IIdentity Identity { get; private set; }

        public bool IsInRole(string role)
        {
            return Array.BinarySearch(_roles, role) >= 0 ? true : false;
        }

        public CustomPrincipal(IIdentity identity, string[] roles)
        {
            Identity = identity;

            _roles = new string[roles.Length];

            roles.CopyTo(_roles, 0);

            Array.Sort(_roles);
        }
    }

 public class CustomPrincipalSerializeModel
    {
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string MiddleName { get; set; }
        public string RoleName { get; set; }
        public string RoleNameCode { get; set; } // English name of role like 'Administrator'
    }

В Global.asax добавить

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

           // Add this
            PostAuthenticateRequest += Application_PostAuthenticateRequest;
        }



  protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
        {
            if (User.Identity.IsAuthenticated)
            {
                //Do stuff here
                HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

                if (authCookie != null)
                {
                    FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

                    JavaScriptSerializer serializer = new JavaScriptSerializer();

                    var serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);

                    var roles = new List<string>() { serializeModel.RoleNameCode }; // English name of role like 'Administrator'

                    var newUser = new CustomPrincipal(User.Identity, roles.ToArray())
                    {
                        Id = serializeModel.Id,
                        FirstName = serializeModel.FirstName,
                        LastName = serializeModel.LastName,
                        MiddleName = serializeModel.MiddleName,
                        RoleName = serializeModel.RoleName // Custom name of role i.e. in Spanish I use it to display for user
                    };


                      HttpContext.Current.User = newUser;
                }
            }


        }

Ваш метод входа в систему должен получить дополнительные данные пользователя и сохранить в файлах cookie

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            try
            {
                var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);

                switch (result)
                {
                    case SignInStatus.Success:

                        var user = User.Identity;
                        try
                        {
                            ApplicationDbContext context = new ApplicationDbContext();

                            var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

                            string userId = UserManager.FindByName(model.UserName)?.Id;

                            var s = UserManager.GetRoles(userId);
                             // db is EF context and UsersViews is user SQL View
                            var u = db.UsersViews.First(x => x.Id == userId);

                            var serializeModel = new CustomPrincipalSerializeModel
                            {
                                Id = u.Id,
                                FirstName = u.FirstName,
                                LastName = u.LastName,
                                MiddleName = u.MiddleName,
                                RoleName = u.RoleName,
                                RoleNameCode = u.RoleNameCode
                            };
                            JavaScriptSerializer serializer = new JavaScriptSerializer();
                            string userData = serializer.Serialize(serializeModel);
                            FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, DateTime.Now.AddMinutes(20), false, userData);
                            string encTicket = FormsAuthentication.Encrypt(authTicket);
                            HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
                            Response.Cookies.Add(faCookie);

                            return RedirectToAction("Index", "Home");

                        }
                        catch (Exception ex)
                        {

                            return View("Lockout");
                        }
                    case SignInStatus.LockedOut:
                        return View("Lockout");
                    case SignInStatus.RequiresVerification:
                        return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
                    case SignInStatus.Failure:
                    default:
                        ModelState.AddModelError("", "Invalid login attempt.");
                        return View(model);
                }
            }
            catch (Exception ex)
            {

                throw;
            }

        }

И в вашем частичном представлении, как в моем случае в _LoginPartial.cshtml

@* here put path where you keep CustomPrincipal class *@
@using GJob.Models.Views  

@if (Request.IsAuthenticated)
{
    using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
    {
        @Html.AntiForgeryToken()
        <div class="form-inline my-2 my-lg-0 " style="margin-left:2em; margin-right:0em;">
            <label class="form-control-sm mr-sm-2">@User.Identity.Name, @( (User as CustomPrincipal).LastName ) @( (User as CustomPrincipal).FirstName )  @( (User as CustomPrincipal).MiddleName ), @( (User as CustomPrincipal).RoleName )</label>
            <a href="javascript:document.getElementById('logoutForm').submit()" class="btn btn-outline-primary btn-sm my-2 my-sm-0">Выход</a>
        </div>
    }
}
else
{
    <form class="navbar-right">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item">
                <a id="loginLink" href="@Url.Content("~/Account/Login")" class="nav-link"><span class="glyphicon glyphicon-log-in"></span> Вход</a>
            </li>
        </ul>
    </form>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...