ASP.NET MVC结合JavaScript登录、校验和加密
更新时间:2021年9月22日 10:06 点击:1627
最近闲来无事给自己写了家庭财务收支管理系统,也就包含支出管理,收入管理和一些统计功能。
先说登录模块,因为涉及GET和POST请求,这些东西都是能被监控和抓取的所以就考虑这使用RSA加密解密方式传输用户名和密码参数,页面JS如下:
/*需要引入三个JS文件,BigInt.js、RSA.js和Barrett.js,用到cookie则需要引入jquery.cookie.js文件*/ //与后台交互获取公钥 function getPublicKey() { var pubKey = ''; if ($.cookie('publicKey') == null) { $.ajax({ url: "/Account/GetRsaPublicKey", type: "get", contentType: "application/x-www-form-urlencoded; charset=utf-8", async: false, data: {}, dataType: "json", success: function (data) { if (data.Code == 0) { pubKey = data.RsaPublicKey + "," + data.Key; $.cookie('publicKey', pubKey, { expires: 1 / 1440 }); } else { Config.Method.JudgeCode(data, 1); } } }); } else { pubKey = $.cookie('publicKey'); } return pubKey; } //公钥加密用户密码Pwd为RSA加密后参数 function rsaEncrypt(pwd) { var publicKey = getPublicKey(); setMaxDigits(129); var rsaKey = new RSAKeyPair(publicKey.split(",")[0], "", publicKey.split(",")[1]); var pwdRtn = encryptedString(rsaKey, pwd); return pwdRtn + "," + publicKey.split(",")[2]; } //POST登录请求,参数 <script type="text/javascript"> $(function () { $('#btnSubmit').live('click', function () { var uName = $('#u').val(); var pwd = $('#p').val(); if (uName == '') { alert('用户名不能为空'); return; } if (pwd == '') { alert('用户密码不能为空'); return; } var enPwd = rsaEncrypt(pwd); $.ajax({ type: "POST", url: "/Account/UserLogin", data: { 'UserName': uName, 'Pwd': enPwd.split(",")[0], 'Key': enPwd.split(",")[1], 'RUrl': $('#hiddenUrl').val() }, contentType: "application/x-www-form-urlencoded; charset=utf-8", async: false, dataType: "json", success: function (data) { if (data.result == true) { window.location.href = data.url; return false; } else { $('#msg').text(data.message); } }, error: function (XMLHttpRequest, textStatus, errorThrown) { $('#msg').text(XMLHttpRequest.status + '||' + XMLHttpRequest.readyState + '||' + textStatus); } }); }); }) </script>
前台加密完成后就需要后台做解密处理,解密完成后需要使用MD5加密现有密码与数据库中用户密码进行比较验证,如果验证通过则需要写入cookie以便下次用户能自 动登录,由于cookie中我不希望用户名和密码都明码存储,我这里用到了AES加密的方式,自定义一个32位的加密密钥对cookie进行加密解密处理,后台c#代码如下:
[HttpPost] public JsonResult UserLogin(string UserName, string Pwd, string Key, string RUrl) { string privateKey = Common.CacheGet(Key) as string; if (!string.IsNullOrEmpty(privateKey)) { if (string.IsNullOrEmpty(UserName)) { return Json(new { result = false, message = "用户名为空" }, JsonRequestBehavior.AllowGet); } if (string.IsNullOrEmpty(Pwd)) { return Json(new { result = false, message = "用户密码为空" }, JsonRequestBehavior.AllowGet); } string pwd = Common.DecryptRSA(Pwd, privateKey);//私钥解密 string md5Pwd = Common.NoneEncrypt(Common.NoneEncrypt(Common.NoneEncrypt(pwd, 1), 1), 1);//将解密后的值md5加密3次 AccountUnserInfo userInfo = bll.GetUserInfo(UserName.Trim(), md5Pwd); if (userInfo != null && userInfo.U_Id > 0)//用户信息存在 { //用户名、密码放入cookie HttpCookie cookie = new HttpCookie("fw_izz"); //AES加密Cookie cookie["u_name"] = AesEncryptHelper.EncryptAes(UserName); cookie["u_pwd"] = AesEncryptHelper.EncryptAes(pwd); cookie.Expires = DateTime.Now.AddDays(7); Response.Cookies.Add(cookie); if (!string.IsNullOrEmpty(RUrl))//接收隐藏域中的值 { return Json(new { result = true, message = "成功", url = RUrl }); } else { return Json(new { result = true, message = "成功", url = "/AccountDetail/Index" }); } } else { return Json(new { result = false, message = "用户信息不存在", url = "/Account/Index" }); } } else { return Json(new { result = false, message = "非法秘钥", url = "/Account/Index" }); } }
各种加密解密方法、Cache操作以及cookie操作代码如下:
public class Common { /// <summary> /// 产生一组RSA公钥、私钥 /// </summary> /// <returns></returns> public static Dictionary<string, string> CreateRsaKeyPair() { var keyPair = new Dictionary<string, string>(); var rsaProvider = new RSACryptoServiceProvider(1024); RSAParameters parameter = rsaProvider.ExportParameters(true); keyPair.Add("PUBLIC", BytesToHexString(parameter.Exponent) + "," + BytesToHexString(parameter.Modulus)); keyPair.Add("PRIVATE", rsaProvider.ToXmlString(true)); return keyPair; } /// <summary> /// RSA解密字符串 /// </summary> /// <param name="encryptData">密文</param> /// <param name="privateKey">私钥</param> /// <returns>明文</returns> public static string DecryptRSA(string encryptData, string privateKey) { string decryptData = ""; try { var provider = new RSACryptoServiceProvider(); provider.FromXmlString(privateKey); byte[] result = provider.Decrypt(HexStringToBytes(encryptData), false); ASCIIEncoding enc = new ASCIIEncoding(); decryptData = enc.GetString(result); } catch (Exception e) { throw new Exception("RSA解密出错!", e); } return decryptData; } private static string BytesToHexString(byte[] input) { StringBuilder hexString = new StringBuilder(64); for (int i = 0; i < input.Length; i++) { hexString.Append(String.Format("{0:X2}", input[i])); } return hexString.ToString(); } public static byte[] HexStringToBytes(string hex) { if (hex.Length == 0) { return new byte[] { 0 }; } if (hex.Length % 2 == 1) { hex = "0" + hex; } byte[] result = new byte[hex.Length / 2]; for (int i = 0; i < hex.Length / 2; i++) { result[i] = byte.Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier); } return result; } private static ObjectCache Cache { get { return MemoryCache.Default; } } /// <summary> /// 获取缓存 /// </summary> /// <param name="key"></param> /// <returns></returns> public static object CacheGet(string key) { return Cache[key]; } /// <summary> /// 设置缓存 /// </summary> /// <param name="key"></param> /// <param name="data"></param> /// <param name="cacheTime"></param> public static void CacheSet(string key, object data, int cacheTime) { CacheItemPolicy policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime); Cache.Add(new CacheItem(key, data), policy); } /// <summary> /// 判断缓存是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool IsSet(string key) { return (Cache[key] != null); } /// <summary> /// 缓存失效 /// </summary> /// <param name="key"></param> public static void CacheRemove(string key) { Cache.Remove(key); } /// <summary> /// 对字符串进行加密(不可逆) /// </summary> /// <param name="Password">要加密的字符串</param> /// <param name="Format">加密方式,0 is SHA1,1 is MD5</param> /// <returns></returns> public static string NoneEncrypt(string Password, int Format) { string strResult = ""; switch (Format) { case 0: strResult = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "SHA1"); break; case 1: strResult = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "MD5"); break; default: strResult = Password; break; } return strResult; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
相关文章
- 这篇文章主要为大家详细介绍了ASP.NET购物车的实现过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
- 在很多网站用户先访问一个要登录的页面,但当时没有登录后来登录了,等待用户登录成功之后肯定希望返回到上次访问的页面,下面我就来给大家介绍登录后跳转回原来要访问的页...2016-11-25
- 在开发过程中,使用Visual Studio的断点调试功能可以很方便帮我们调试发现程序存在的错误,同样Visual Studio也支持对SQL Server里面的存储过程进行调试,下面就让我们看看具体的调试方法。...2021-09-22
- 本文章完美的利用了php的curl功能实现模拟登录discuz以及模拟发帖,本教程供参考学习哦。 代码如下 复制代码 <?php $discuz_url = ‘ht...2016-11-25
- 这篇文章主要给大家介绍了关于Nest.js参数校验和自定义返回数据格式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-28
校验非空的注解@NotNull如何取得自定义的message
这篇文章主要介绍了校验非空的注解@NotNull如何取得自定义的message,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-29Ruby on Rails实现最基本的用户注册和登录功能的教程
这里我们主要以has_secure_password的用户密码验证功能为中心,来讲解Ruby on Rails实现最基本的用户注册和登录功能的教程,需要的朋友可以参考下...2020-06-30- 什么是SSO?单点登录SSO(Single Sign-On)是身份管理中的一部分。SSO的一种较为通俗的定义是:SSO是指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用中的受保护...2015-11-08
- 【问题描述】:同一用户在同一时间多次登录如果不能检测出来,是危险的。因为,你无法知道是否有其他用户在登录你的账户。如何禁止同一用户多次登录呢? 【解决方案】 (1) 每次登录,身份认证成功后,重新产生一个session_id。 s...2015-11-24
ASP.NET Core根据环境变量支持多个 appsettings.json配置文件
这篇文章主要介绍了ASP.NET Core根据环境变量支持多个 appsettings.json配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22- 这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
- 什么是SSO?单点登录SSO(Single Sign-On)是身份管理中的一部分。SSO的一种较为通俗的定义是:SSO是指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用中的受保护...2015-11-08
- 这篇文章主要为大家详细介绍了vue实现用户登录切换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-04-22
详解element-ui 表单校验 Rules 配置 常用黑科技
这篇文章主要介绍了element-ui 表单校验 Rules 配置 常用黑科技,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-07-11- 这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
- 出现phpmyadmin不能登录是我在修改我mysql服务器密码之后导致的,后来百度了相关的原因,原来是修改了mysql密码之后我们还需要在phpmyadmin目录中去修改config.inc.php中...2016-11-25
C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?
这篇文章主要介绍了C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?,这也小编做.NET项目时经常思考和让人混乱的一个问题,这篇文章写的挺好,一下清晰了许多,需要的朋友可以参考下...2020-06-25Vue-Element-Admin集成自己的接口实现登录跳转
关于这个Vue-element-admin中的流程可能对于新的同学不是很友好,所以本文将结合实例代码,介绍Vue-Element-Admin集成自己的接口实现登录跳转,感兴趣的小伙伴们可以参考一下...2021-06-23详解ASP.NET Core 中基于工厂的中间件激活的实现方法
这篇文章主要介绍了ASP.NET Core 中基于工厂的中间件激活的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22- 这篇文章主要介绍了浅谈js二维码扫码登录是什么原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-13