• 过滤器实现Token验证(登录验证+过期验证)---简单的实现


    功能:登录验证+过期验证+注销清除cookie+未注销下关闭或刷新浏览器仍可直接访问action
    概述:token只存在客户端cookie,后端AES加密+解密+验证,每一次成功访问action都会刷新token包括过期时间

    1.过滤器

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;
    using System.Web;
    using System.Web.Mvc;
    
    namespace TokenTest.MyActionFilter
    {
        /// <summary>
        /// <param name="Die_Time">Die_Time//设置token过期时间小于7days</param>
        /// <param name="Jump_Page">Jump_Page//设置token验证失败后跳转页面如/Login/Index;可携带参数/Login/Index?******</param>
        /// </summary>
        public class Token_Filter:ActionFilterAttribute//继承ActionFilterAttribute类
        {
            public  int Die_Time { get; set;}//设置token过期时间<7days
            public  string Jump_Page { get; set; }//设置token验证失败后跳转页面如/Login/Index;可携带参数/Login/Index?******
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                var token = HttpContext.Current.Request.Cookies["Token"];
                if (token==null)
                {
                    HttpContext.Current.Response.Write("<script language='javascript'>alert('您未登陆,请先登陆!');location.href='" + Jump_Page + "' ;</script>");
                }
                else
                {
                    string U_ID = AESDecrypt(token.Value.ToString(), "jjq").Split('_')[0];
                    DateTime Token_Time = Convert.ToDateTime(AESDecrypt(token.Value.ToString(), "jjq").Split('_')[1]);
                    //检验过期时间;token理论上验证有效期:Die_Time<7天/////每次加载过滤action都会重新设置时间(可改)
                    if (Token_Time.AddDays(Die_Time) < DateTime.Now)
                    {
                        HttpContext.Current.Response.Write("<script language='javascript'>alert('登陆过期,请重新登录!');location.href='" + Jump_Page + "' ;</script>");
                    }
                    else
                    {
                        //完全验证通过后重新改写token并覆写在cookie里
                        Set_Token(U_ID);
                    }
                }
                
            }
            public static void Set_Token(string user_name)
            {
                var Token = AESEncrypt(user_name + "_" + DateTime.Now.ToString() + "_" + Guid.NewGuid(), "jjq");//Token加密;;jjq加密密匙
                HttpContext.Current.Response.Cookies["Token"].Value = Token;
                HttpContext.Current.Response.Cookies["Token"].Expires = DateTime.Now.AddDays(7);//设置Token客户端保留时间7天
            }
    
            #region
            /// <summary>
            /// 加密解密功能代码片段
            /// </summary>
            //AES密钥向量
            private static readonly byte[] _aeskeys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
            /// <summary>
            /// AES加密
            /// </summary>
            /// <param name="encryptStr">加密字符串</param>
            /// <param name="encryptKey">密钥</param>
            /// <returns></returns>
            public static string AESEncrypt(string encryptStr, string encryptKey)
            {
                if (string.IsNullOrWhiteSpace(encryptStr))
                    return string.Empty;
    
                encryptKey = SubString(encryptKey, 0, 32);
                encryptKey = encryptKey.PadRight(32, ' ');
    
                //分组加密算法
                SymmetricAlgorithm des = Rijndael.Create();
                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptStr);//得到需要加密的字节数组 
                //设置密钥及密钥向量
                des.Key = Encoding.UTF8.GetBytes(encryptKey);
                des.IV = _aeskeys;
                byte[] cipherBytes = null;
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(inputByteArray, 0, inputByteArray.Length);
                        cs.FlushFinalBlock();
                        cipherBytes = ms.ToArray();//得到加密后的字节数组
                        cs.Close();
                        ms.Close();
                    }
                }
                return Convert.ToBase64String(cipherBytes);
            }
            /// <summary>
            /// AES解密
            /// </summary>
            /// <param name="decryptStr">解密字符串</param>
            /// <param name="decryptKey">密钥</param>
            /// <returns></returns>
            public static string AESDecrypt(string decryptStr, string decryptKey)
            {
                if (string.IsNullOrWhiteSpace(decryptStr))
                    return string.Empty;
    
                decryptKey = SubString(decryptKey, 0, 32);
                decryptKey = decryptKey.PadRight(32, ' ');
    
                byte[] cipherText = Convert.FromBase64String(decryptStr);
    
                SymmetricAlgorithm des = Rijndael.Create();
                des.Key = Encoding.UTF8.GetBytes(decryptKey);
                des.IV = _aeskeys;
                byte[] decryptBytes = new byte[cipherText.Length];
                using (MemoryStream ms = new MemoryStream(cipherText))
                {
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                        cs.Read(decryptBytes, 0, decryptBytes.Length);
                        cs.Close();
                        ms.Close();
                    }
                }
                return Encoding.UTF8.GetString(decryptBytes).Replace("", "");//将字符串后尾的''去掉
            }
    
            public static string SubString(string sourceStr, int startIndex, int length)
            {
                if (!string.IsNullOrEmpty(sourceStr))
                {
                    if (sourceStr.Length >= (startIndex + length))
                        return sourceStr.Substring(startIndex, length);
                    else
                        return sourceStr.Substring(startIndex);
                }
    
                return "";
            }
            #endregion
        }
    }
    
    

    2.使用方法

    1.需要过滤的Controller中引用(注意给参数)

    
    using System.Web.Mvc;
    using TokenTest.MyActionFilter;
    
    namespace TokenTest.Controllers
    {
    
        public class adminController : Controller
        {
            // GET: admin
            [Token_Filter(Die_Time=3,Jump_Page = "/Login/Index")]
            public ActionResult Index()
            {
                return View();
            }
        }
    }
    
    
    

    2.LoginController中引用Token_Filter.Set_Token()方法;激活设置token+注销按钮(清除cookie)

    using System;
    using System.Web.Mvc;
    using TokenTest.MyActionFilter;
    
    namespace TokenTest.Controllers
    {/// <summary>
     /// ////////////////////////////////////////////////
     /// </summary>
    
        public class LoginController : Controller
        {
            // GET: Login
            public ActionResult Index()
            {
                return View();
            }
            public ActionResult Logout()
            {
                //注销按钮---清除cookie
                Response.Cookies["Token"].Expires = DateTime.Now.AddDays(-1);
                return View("Index");
            }
            public ActionResult Login()
            {
                var get_name = Request["name"];
                var get_pwd = Request["pwd"];
                JJQPractice visitor = JJQPractice.SingleOrDefault(new { name = get_name });//得到对应输入的账号的集
                if (visitor != null)//验证输入的账号是否存在
                {
                    if (visitor.pwd == get_pwd)//验证密码是否正确
                    {
                        Token_Filter.Set_Token(get_name);
                        return RedirectToAction("Index", "admin"); //密码正确后跳转到查询视图
                    }
                    else
                    {
                        Response.Write("登录失败!密码错误.");
                        return View("Index");
                    }
                }
                else
                {
                    Response.Write("登录失败,用户名不存在.");
                    return View("Index");
                }
            }
        }
    }
    
    
    
    
    <h2>Logn-Index</h2>
    <br><br>
    <form action="/Login/Login" method="post">
        姓名:<input type="text" name="name"/><br><br>
        密码:<input type="text" name="pwd"/><br><br>
        <input type="submit" value="提交"/><br><br>
    </form>
    
    
    
    <h2>Index</h2>
    <form action="/admin/Index" method="post">
        <input  name="h" value="6666"/>
        <input type="submit" value="按钮"/><br /><br />
    </form>
    <form action="/Login/Logout" method="post">
        <input type="submit" value="注销_清除cookie" />
    </form>
    
    
  • 相关阅读:
    Swift 中的函数
    Swift中的字典
    IOS组件绑定无效错误
    求余运算符
    Swift中的数组
    swift网络编程入门应用:天气预报
    iOS开发网络篇—Reachability检测网络状态
    IP-Address TextBox
    C#创建用户控件
    C# 判断 当前设备的IP地址、默认网关、子网掩码在不在同一网段内
  • 原文地址:https://www.cnblogs.com/jsll/p/11746412.html
Copyright © 2020-2023  润新知