Я нашел ответ здесь 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>
}