Forms form validation in MVC and the realization of the ActionFilterAttribute interceptor

Preface

Authentication and authorization mechanism
Authentication is the process of determining the identity of a user. After the user is authenticated, the developer
can determine whether the user has the right to continue the operation. If there is no authentication, the
entity cannot be authorized.
Authorization is to determine whether the authenticated user has the right to access a certain part of the application, a certain
point, or only a specific set of data provided by the application.

Today I will share about Forms form login verification in .NET MVC and ActionFilterAttribute role interception. There are two ways to log in.
The first is: form submission.
The second: Ajax asynchronous submission. Not much to say, just go to the code.

Login summary flowchart

Insert picture description here

Web.Config configuration

(1) Add an authentication node in the system.web node in the web.Config configuration .

(2) Mode: ASP.NET supports 3 authorization methods
                     ● Windows : IIS authentication. Very useful in an intranet environment.
                     ● Passport : Microsoft centralized authentication,-one login can access all member
sites, and charges are required.
                     ● Forms : form verification, verification of account/password, the best and popular verification
method for Web programming .
                     Here we choose Forms form validation.

(3) About the attributes used in the Forms node:
          ●name: is the name given to the cookie to save the user between requests, the default value is .Aspxauth
          ●loginurl: the page that needs to be processed for authentication. We are here to deal with the login page. If a valid verification cookie is not found, specify the URL of Redingxi
          ● timeout: Specify the time (minutes) for the cookie to expire. Here, specify the expiration time as 20 minutes.

 <system.web>
         <authentication mode="Forms">
             <forms name="auth" loginUrl="/Account/Login"   timeout="20" > </forms>
        </authentication>
  </system.web>

Login view

(1) What needs to pay attention to the form in the view is the action submission address. In addition, in the controller, if the submission method is specified, then pay attention to the method submission method. And should use post. There is also the name attribute value of the user box and the password box. The name of the passed parameter is the relevant name value.

  <form class="layui-form" id="form" action="/Account/Login" method="post">
                    <label class="layui-form-label" >用户名</label>
                    <input type="text" name="LoginId" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" >
                    <label class="layui-form-label">密码</label>
                    <input type="password" name="LoginPWD" required lay-verify="required" placeholder="请输入密码" autocomplete="off" >
                    @*方式一,表单提交*@
                    <button class="layui-btn lg_btn" type="submit" lay-submit lay-filter="formDemo">立即登录</button>
  </form>

Log in to the controller

(1) Through the user name and password entered by the view user, the entity class of the user table in the database to query and return personal information.

(2) Determine whether the status of the individual is resigned

(3) When the login password is successful and the personal status is active, start to create a bill. FormsAuthenticationTicket. The parameters are: version number, user name, ticket creation date, ticket expiration time, whether to continue the ticket, user-defined data.

(4) UserData in the ticket FormsAuthenticationTicket can only put string types, if we want to store user objects in it. You can serialize objects into json format strings. If you want to use it, just deserialize it.

(5) FormsAuthentication. Encrypt is the method used to encrypt the newly created bill. Use the ticket to generate cookies and save them to Cookies. Note that the Key of the Cookie refers to the name of the form authentication FormsAuthentication.FormsCookieName

(5) Jump page, here is the employee index page.

        [HttpPost]
        public ActionResult Login(string LoginId, string LoginPWD)
        {
    
    
                                                //MD5加密
            LoginPWD = Converters.ToolMD5Encrypt(LoginPWD);
            employee employee = new employee();
            employee.Login_name = LoginId;
            employee.Login_pwd = LoginPWD;
            if (ES.LoginVilidate(employee) != null)
            {
    
    
                //通过输入的用户名和密码进行数据库匹配并返回实体信息
                employee SuccesEntity = ES.LoginVilidate(employee);
                if (SuccesEntity.Status == "1")
                {
    
    
                    ViewBag.LoginMesssage = "用户不存在";
                }
                else
                {
    
    
                    //创建一个授权对象类  存储相关信息
                    Authinfor AuthEntity = new Authinfor {
    
     Emp_id = SuccesEntity.Emp_id, Name = SuccesEntity.Name, Roles_name = SuccesEntity.Roles_name };
                    //序列化授权对象类,用于放入票据中的用户自定义事件
                    string userDataJson = JsonConvert.SerializeObject(AuthEntity);
                    FormsAuthenticationTicket Tick = new FormsAuthenticationTicket(
                      1,                                                                    //版本号
                      SuccesEntity.Name,                                                    //用户名
                      DateTime.Now,                                                         //创建票据日期
                      DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),    //票据持续时间
                      false,                                                                //是否持久性
                     userDataJson);                                                         //用户自定义存储数据
                    string eny = FormsAuthentication.Encrypt(Tick);                         //对创建好了的票据进行加密
                    //将票据保存在
                    HttpCookie HK = new HttpCookie(FormsAuthentication.FormsCookieName, eny);
                    Response.Cookies.Add(HK);
                    return Redirect("/Employees/index");
                }
            }
            else
            {
    
    
                ViewBag.LoginMesssage = "登录失败";
            }
            return View();
        }

Note: I am here because when registering an employee, the password is stored in the database using MD5 encryption. Therefore, when judging whether the employee entered the password is correct, it is necessary to re-encrypt the unified format on both sides with MD5, and then query the relevant information in the database.

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="value">要加密的字符串</param>
        /// <returns>加密好的字符串</returns>
        public static string ToolMD5Encrypt(string value)
        {
    
    
            try
            {
    
    
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] btSource = System.Text.Encoding.Default.GetBytes(value);
                byte[] btResult = md5.ComputeHash(btSource);
                string encryptData = "";
                for (int i = 0; i < btResult.Length; i++)
                {
    
    
                    encryptData += btResult[i].ToString("X");
                }
                return encryptData;
            }
            catch (Exception ex)
            {
    
    
                throw ex;
            }
        }

Then the above completes the process of form verification. The next thing to note is. Which view page needs to be authenticated before it can be accessed? Just add the [Authorize] logo.

(1) In the login controller, I am redirected to the index page of the employee after successful verification. So I added a certification mark on the employee index controller.

        // GET: Employees
        [CheckFilter("经理")]
        [Authorize]
        public ActionResult Index()
        {
    
    
            return View();
        }

(2) The role interception will be completed next. In other words, not every page can be accessed by any employee.

(3) Create a new class with a custom class name, and here is CheckFilter.

(4) Custom interceptor, inherit and inherit the ActionFilterAttribute abstract class, rewrite the required methods, and look at the method signature and rewrite of the ActionFilterAttribute class.
     ●OnActionExecuting: the virtual method to be processed when entering the Action, where the received Request request can be processed or intercepted.
     ●OnActionExecuted: You have entered Action, here you can continue to process something or intercept it.
     ●OnResultExecuting: Before responding to Result, you can continue to process something or intercept it.
     ●OnResultExecuted: After responding to Result, you can continue to process something or intercept.

Custom interceptor class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Newtonsoft.Json;
using Model.BusinessMsage;
namespace TestHoses.Code
{
    
    
 public class CheckFilter : ActionFilterAttribute
 {
    
    
     protected string Roles {
    
     get; set; }
     protected bool IsAjaxs {
    
     get; set; }

     /// <summary>
     /// 构造函数
     /// </summary>
     /// <param name="roles"></param>
     /// <param name="ajaxs"></param>
     public CheckFilter(string roles="", bool ajaxs = false)
     {
    
    
         Roles = roles;
         IsAjaxs = ajaxs;
     }


     public override void OnActionExecuting(ActionExecutingContext filterContext)
     {
    
    
         //判断当前请求类型是否为Ajax请求
         if (filterContext.HttpContext.Request.IsAjaxRequest())
         {
    
    
             this.IsAjaxs = true;
         }
     }


     public override void OnActionExecuted(ActionExecutedContext filterContext)
     {
    
    
         //获取当前验证成功票据中的用户自定义数据
         string userData = ((FormsIdentity)filterContext.HttpContext.User.Identity).Ticket.UserData;
         //反序列化获取对象
         Authinfor authinfor = JsonConvert.DeserializeObject<Authinfor>(userData);
         if (!authinfor.Roles_name.Split(',').Contains(Roles))
         {
    
    
             if (!IsAjaxs)
             {
    
    
                 filterContext.HttpContext.Response.Redirect("/Home/Error");
             }
             else
             {
    
    
                 filterContext.HttpContext.Response.Write("{\"meeage:\"你没权限\"}");
                 filterContext.HttpContext.Response.End();
             }
         }
         else {
    
    
             if (IsAjaxs) {
    
    
                 
                 filterContext.HttpContext.Response.Write("{\"meeage:\"true\"}");
                 filterContext.HttpContext.Response.End();
             }
         }
     }
 }
}

(1) Encapsulate field attributes, role names, whether it is an ajax request.

(2) Before the Action is executed, judge Request.IsAjaxRequest() to determine whether it is an AJax request.

(3) After the Action is executed, first obtain the current authorization information. That is, the userData stored in the ticket. Before storing, we serialized it, so we need to deserialize it back when reading.

(4) Determine whether the user role is legal and whether it is an Ajax request.

(5) Why is it necessary to judge whether it is an ajax request? Because when we want to intercept processing, we need to redirect to other page addresses and tell the user that they do not have permission to access. Ajax is a partial refresh, and the Response.Redirect() redirect address is invalid for it. Therefore, we need to determine the request type and handle some things according to the request type. If it is an Ajax request, then the specified information or status is returned, and the front-end js is processed according to the specified information or status. If it is not an Ajax request, it will directly redirect the relevant page address and give a prompt.

Guess you like

Origin blog.csdn.net/WenRouDG/article/details/107929082