ASP.NET MVC结合JavaScript登录、校验和加密

最近闲来无事给自己写了家庭财务收支管理系统,也就包含支出管理,收入管理和一些统计功能。

先说登录模块,因为涉及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;
    }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 原生js验证简洁注册登录页面

    序 一个以js验证表单的简洁的注册登录页面,不多说直接上图 效果 主要文件 完整代码 1 sign_up.html 注册表单 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>sign-up</title> <link rel="stylesheet" href="css

  • 拦截JSP页面,校验是否已登录详解及实现代码

    拦截JSP页面,校验是否已登录 最近使用struts2做项目,需要拦截JSP以校验是否已经登,但struts2的过滤器链只能过滤action.后来发现在web.xml里可以直接增加javax.servlet.Filter实现类的过滤器,可以过滤JSP.请看代码 Filter实现类 <span style="font-size:18px;">package com.common; import java.io.IOException; import javax.servlet

  • js制作带有遮罩弹出层实现登录注册表单特效代码分享

    本文实例讲述了js制作带有遮罩弹出层实现登录注册表单代码特效代码.分享给大家供大家参考.具体如下: 运行效果图:                     ----------------------查看效果   源码下载----------------------- 小提示:浏览器中如果不能正常运行,可以尝试切换浏览模式. jquery制作的带有遮罩弹出层实现登录注册等表单的特效源码,是一段实现了点击后在原始页面上弹出想用页面的代码.  为大家分享的js制作带有遮罩弹出层实现登录注册表单代码特效

  • JavaScript注册时密码强度校验代码

    密码强度有4个状态,分别如下图. 无密码状态 密码低级状态 密码中级状态 密码高级状态 实现的代码主要如下: HTML代码 <input name="password" type="PassWord" onKeyUp="CheckIntensity(this.value)"> <table border="0" cellpadding="0" cellspacing="0&quo

  • js实现登录注册框手机号和验证码校验(前端部分)

    开发的很多场景中都会用到手机号的校验和验证码的校验,具体实现如下 <div> <input type="text" name="phonenumber" placeholder="请输入您的手机号码" /> <input type="text" name="verify" placeholder="请输入验证码" /><input type=&q

  • JavaScript 完成注册页面表单校验的实例

    1.步骤分析 第一步:确定事件(onsubmit)并为其绑定一个函数 第二步:书写这个函数(获取用户输入的数据<获取数据时需要在指定位置定义一个 id>) 第三步:对用户输入的数据进行判断 第四步:数据合法(让表单提交) 第五步:数据非法(给出错误提示信息,不让表单提交) 问题:如何控制表单提交? 关于事件 onsubmit:一般用于表单提交的位置,那么需要在定义函数的时候给出一个 返回值. onsubmit = return checkForm() 2.完成注册页面表单校验 <!DOC

  • JavaWeb实现用户登录注册功能实例代码(基于Servlet+JSP+JavaBean模式)

    下面通过通过图文并茂的方式给大家介绍JavaWeb实现用户登录注册功能实例代码,一起看看吧. 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+JavaBean模式(MVC)适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据. Servlet+JSP+JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式. 这里以一个最常用的用户登录注册程序来讲解Servlet+JS

  • js简单实现用户注册信息的校验代码

    register.html 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta htt

  • Angular.js与node.js项目里用cookie校验账户登录详解

    前言 最近的新项目中,用户登录需要采用cookie来记住用户,校验身份.所以本文就把实现的过程总结出来分享给大家,需要的朋友们可以参考学习. 在header中携带authId登录 在之前老的项目里,没有采用cookie来记录用户登录状态,而是在请求的header中携带一个身份标识来校验,大致方案如下: 客户端使用post请求提交user.password给服务端进行登录操作: 服务端校验用户是否合法,如果合法将产生一个唯一的身份标识authId,返回给客户端,客户端将此authId存放本地(如l

  • Servlet+JavaBean+JSP打造Java Web注册与登录功能

    采用Java Web所实现的MVC结构图如下,其中控制器部分采用Servlet来实现,模型部分采用JavaBean来实现,而大部分的视图采用Jsp页面来实现. 思想基础 JSP+JavaBean两层结构工作原理应该是比较熟悉的,也比较好理解. 但是有一点必须要清楚就是用户通过浏览器来发送网页的请求,此请求到达服务器后在服务器端查找对应的网页,如果是首次请求(第二次就不用解释执行了),对于JSP来说要生成Servlet,然后通过Servlet引擎来执行 Servlet,把调用JavaBean的结果

随机推荐