. net MVC uses iprincipal for form login, namely authority verification (3)

Time:2020-1-18

. net MVC uses iprincipal to perform form login, i.e. authority verification, for your reference. The details are as follows

1. Add user class in MVC project, and add necessary attributes according to actual project requirements

public class UserData
 {
 /// <summary>
 /// ID
 /// </summary>
 public int UserId { get; set; }

 /// <summary>
 ///User name
 /// </summary>
 public string UserName { get; set; }

 /// <summary>
 ///Role ID list
 /// </summary>
 public List<int> Roles { get; set; }
 }

2. Add a class principal to implement iprincipal interface

public class Principal : IPrincipal
 {
 public IIdentity Identity { get; private set;}

 public UserData Account { get; set; }

 /// <summary>
 ///Constructor
 /// </summary>
 /// <param name="ticket"></param>
 /// <param name="account"></param>
 public Principal(FormsAuthenticationTicket ticket, UserData account)
 {
  if (ticket == null)
  throw new ArgumentNullException("ticket");
  if (account == null)
  throw new ArgumentNullException("UserData");

  this.Identity = new FormsIdentity(ticket);
  this.Account = account;
 }

 public bool IsInRole(string role)
 {
  if (string.IsNullOrEmpty(role))
  return true;
  if (this.Account == null || this.Account.Roles == null)
  return false;
  return role.Split(',').Any(q => Account.Roles.Contains(int.Parse(q)));
 }
 }

Iprincipal interface has an object identity, which needs to implement the authentication role method isinrole(). The user data attribute account is added to our implementation class.

The constructor is initialized. The first object is the form validated ticket object. The ticket will carry the user information and save it in the cookie.

3. Create classes to store and read cookies

/// <summary>
 ///Write and read cookies
 /// </summary>
 public class HttpFormsAuthentication
 {
 //Save user information to cookie through ticket encryption
 public static void SetAuthenticationCoolie(UserData account, int rememberDay = 0)
 {
  if (account == null)
  throw new ArgumentNullException("account");

  //Serialize account object
  string accountJson = JsonConvert.SerializeObject(account);
  //Create user ticket
  var ticket = new FormsAuthenticationTicket(1, account.UserName, DateTime.Now, DateTime.Now.AddDays(rememberDay), false, accountJson);
  // encryption
  string encryptAccount = FormsAuthentication.Encrypt(ticket);

  //Create cookies
  var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptAccount)
  {
  HttpOnly = true,
  Secure = FormsAuthentication.RequireSSL,
  Domain = FormsAuthentication.CookieDomain,
  Path = FormsAuthentication.FormsCookiePath
  };

  if (rememberDay > 0)
  cookie.Expires = DateTime.Now.AddDays(rememberDay);

  //Write cookie
  HttpContext.Current.Response.Cookies.Remove(cookie.Name);
  HttpContext.Current.Response.Cookies.Add(cookie);
 }

 //Get cookies and parse user information
 public static Principal TryParsePrincipal(HttpContext context)
 {
  if (context == null)
  throw new ArgumentNullException("context");
  HttpRequest request = context.Request;
  HttpCookie cookie = request.Cookies[FormsAuthentication.FormsCookieName];
  if (cookie == null || string.IsNullOrEmpty(cookie.Value))
  {
  return null;
  }
  //Decrypt coolie value
  FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);

  UserData account = JsonConvert.DeserializeObject<UserData>(ticket.UserData);
  return new Principal(ticket, account);
 }

 }

When storing the cookie, the serialized string accountjson is encrypted by the ticket and saved in the cookie. The specific accountjson is assigned to the UserData attribute of formsauthenticationticket.

You can see that the original user information object is obtained by deserializing ticket.UserData during parsing, and then the Principal object is generated.

Tryparseprincipal, the method used to parse the cookie to get the principle object, will be used when the request is initiated. The returned principle object is assigned to httpcontext.user.

4. Register the application ﹣ postauthenticaterequest event in global.asax to ensure that the user information in the cookie is taken out and assigned to the user before authority verification


protected void Application_PostAuthenticateRequest(object sender, System.EventArgs e)
 {
  HttpContext.Current.User =
  HttpFormsAuthentication.TryParsePrincipal(HttpContext.Current);
 }

5. Integrate the authorizeattribute attribute class and override the authorizecore, handleunauthorizedrequest method

public class FormAuthorizeAttribute : AuthorizeAttribute
 {
 /// <summary>
 ///Enter this method first. In this method, the authorizecore verification logic will be called. If the verification fails, the handleunauthorizedrequest method will be called
 /// </summary>
 /// <param name="filterContext"></param>
 public override void OnAuthorization(AuthorizationContext filterContext)
 {
  base.OnAuthorization(filterContext);
 }

 /// <summary>
 ///Authority verification
 /// </summary>
 /// <param name="httpContext"></param>
 /// <returns></returns>
 protected override bool AuthorizeCore(HttpContextBase httpContext)
 {
  var user = httpContext.User as Principal;
  if (user != null)
  return user.IsInRole(base.Roles);
  return false;
 }

 protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
 {
  //If the verification fails, directly jump to the corresponding page. Note: if the following jump is not Yo Na, the action method will continue to be executed
  filterContext.Result = new RedirectResult("~/Login/Index");
 }
 }

The AuthorizeCore and HandleUnauthorizedRequest methods are called in the method OnAuthorization, and the HandleUnauthorizedRequest method is invoked before AuthorizeCore verification fails.

The verification code is implemented in the authorizecore, and the logic that fails to pass the verification is implemented in the handleunauthorizedrequest method.

6. Add logincontroller to implement login logic


namespace MVCAuthorizeTest.Controllers
{
 public class LoginController : Controller
 {
 [AllowAnonymous]
 // GET: Login
 public ActionResult Index(string returnUrl)
 {
  ViewBag.ReturnUrl = returnUrl;
  return View();
 }

 [HttpPost]
 [AllowAnonymous]
 public ActionResult Index(string name, string password, bool rememberMe, string returnUrl)
 {
  var account = new UserData()
  {
  UserName = name,
  UserId = 110,
  Roles = new List<int>() { 1, 2, 3 }
  };
  HttpFormsAuthentication.SetAuthenticationCoolie(account, rememberMe ? 7 : 0);
  if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\"))
  {
  return Redirect(returnUrl);
  }
  else
  {
  return RedirectToAction("Index", "Home");
  }
 }

 // POST: /Account/LogOff
 [HttpPost]
 public ActionResult LogOff()
 {
  System.Web.Security.FormsAuthentication.SignOut();
  return RedirectToAction("Index", "Home");
 }
 }
}

7. Add feature labels to controllers or actions that need to be verified


 [FormAuthorize(Roles = "1,2")]
 public class HomeController : Controller
 {
 [FormAuthorize]
 public ActionResult Index()
 {
  return View();
 }
 }

Pictured

8. Add global registration filter in add filterconfig to reduce the setting of each action. If there are pages that do not need to be verified, add the [allowanymous] feature

public class FilterConfig
 {
 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
 filters.Add(new HandleErrorAttribute());
 //Global register filter
 filters.Add(new FormAuthorizeAttribute());
 }
 }

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.