欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-11-17 14:32:04
最近闲来无事给自己写了家庭财务收支管理系统,也就包含支出管理,收入管理和一些统计功能。 先说登录模块,因为涉及get和post请求,这些东西都是能被监控和抓取的所以就...

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

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

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