小程序之RSA加密实现接口保护和多并发处理

前言

近期由于客户现场出现了非法接口的调用,为了处理此类问题和杜绝后续问题的出现。针对公司现有的项目实现接口加密,防止接口被恶意的调用。

设计思路:客户端存储超级私钥,客户端返回加密的公钥。客户端先使用超级私钥对公钥进行解密,使用解密出来的公钥对接口进行加密。把加密后的字符串进行验签发送给服务器,服务器进行字符串对比。

相关引用文件

文件的引用这里就只放截图了,源文件网上很容易找到的。这里使用jsencrypt.min.js是为了节省小程序的空间。
在这里插入图片描述在这里插入图片描述

获取服务器的加密公钥

var baseURL = require('./api.js');
var superPrivateKey = "MIIEpQIBAAKCAQEAyNftZEtP9PdwCZT8ZE8xSzuLA8tSZbczwBaLg+NiWKibCGsk11YXYcL8kZ9DBxVdpv1ysp7vGBu6QdmDKeymeae6HCEu3ThDjzGMbCCITswIWjT01Y7Fa6MQlbYJZD55MY3w/ZWDnzsjuTF6l3KJodqUwhXUlUvTbi60gdQXOmgNUE3LkGc9dsDonKBId46WLMY92B3vlLoA/GArBeCZQcwF29ztfrfvRP2tCtvV9tsqoRXSJXzbEgI3fX2/WVt9drXgMd9ZekM53PZwwEHQyEwnLrilOTAzlmzGO2ZbXY+4ahUo2iOH5WAvA65Y/qw7QgIzT24ooJ1HY1eyyFJUnwIDAQABAoIBAQC0lWF/Yi/8RFbaZrkgwAvEZz8xJClsB3NibWL4LQUKTl9HDH9NlrzjS9yoWph7z/wq34u3iyvTc2rfNmG22m88x1CRZkyq36HvKE/oEMA+iTmhUigptHtRsoaA9fIvzfROWB+tAjgcfaI7K3/cmEGj49MJR3Oi4VCzqw7mBPr1qWvNFx5vd4Rwjy4qO5K+BAlx8+yQ87z04tULlzUqBPIPK8WGb98TlG1CmMw5/ZQo1HfjxA82+8AO3qMapPDC6hzUBPvS+AQ2NxRdjceDxPmNzA2s2Kp2DIN3sQalSSy3+9ESLQpwwLhSJSmX/6E1XZFhv76nd3zOtbSUrzLBwzuxAoGBAPaVYfGMod/9eAZGQsCSv3sGQSis//jhjtHxef3VMdhGr3vgCmokLb1RlP50zVYlXYh3qvksn7ZjC5XkVbVDofNC4MJatzi4rIpQ/uUNmlxMMhZkwn8S4C9gIgkxXsY4siSb4zNKT6SxOFazi4qeMbwE+PlaYe2mxwl+iizw4slDAoGBANCDYwNEVFUE6F+ver9Lt25mBVP8L+pOjXSCGb3c9M2YvKVKuEZcOAwE/HnZms5xLAZGG7SCVbkLCUlOHoKigbKYr1jEvujMhbSF0IuhXHSnuvWmUX1HSo/bzdEyLEaQyZ+G2bQpYYUgKjEtfPcbHuDelUw99JY3ghoV04vv3DN1AoGBAK66JaAK/f2BV1Zi3RQmKEbdpLhU9kD+W7yKdt4V/u75D4ogtGCH6F1ZfNFeJM5hRcjYuy87nqSXxHLfTJhYJ17/ydIOg/xOZ/zO7f+SxwmV+HwDxApVbsRDQ3ruH/En5ZupVrJWet8BsSFGsp9z/1vyzhWrJO9ImYsxvmmf+6OPAoGALlMCTFeB5OGSPq/dtWI8/mnsBRyiCIwrIRdGYMgWGxcz0gUnq3oReZoh/XA61GKQRVSOEyxhnxq0lXSlkqBH8EW7rx0GzPGjQtf33Q2cXM5m2ux4bjzIc+2BbFiZPZQtNyPeegg3gjwDI6nXeY6s7YiF4spg7H6oiOMQfKZtZYECgYEAttlJveIjoMWNrnPWeegZ0VU+6HT7A4okcIIE0CLEmE9qVLoGGnehgpntf71spCePJOJhaPydZsDZPSrz916gHtg1vGwoApAgecweom3s95hKyOMsN6LoZRvrR7mx9UQ4Qjaq8bZzzxhF+XsvzC9QYBVUzeZp6y2rkXgKktBQ37c="
var Encrypt = require('../utils/jsencrypt.min.js');
var encryptor = new Encrypt.JSEncrypt();

function timest() {
   
  let tmp = Date.parse(new Date()).toString();
  tmp = tmp.substr(0, 10);
  return tmp;
}

function getPrivatekey() {
   
  return new Promise(function(resolve, reject) {
   
    let time = timest();
    wx.request({
   
      url: baseURL.baseURL + 'api/services/app/Setting/GetCerPriKeyAsync?timestamp=' + time,
      data: '',
      header: {
   },
      method: 'Get',
      success: function(res) {
   
        encryptor.setPrivateKey(superPrivateKey);
        let array = res.data.Result.Data;
        let sourcePrivate = '';
        for (let a = 0; a < array.length; a++) {
   
          // sourcePrivate = encryptor.decrypt(array[0]) + array[1];
          if (a == 0) {
   
            sourcePrivate += encryptor.decrypt(array[a]);
          } else {
   
            sourcePrivate += array[a];
          }
        }
        console.log("原始私钥" + sourcePrivate);
        resolve(sourcePrivate);
      },
      fail: function(res) {
   
        console.log(res)
        reject(res)
      },
      complete: function(res) {
   },
    })
  });
}
module.exports = {
   
  getPrivatekey: getPrivatekey
}
baseURL是定义接口地址,在获取加密公钥的时候由于RSA自身的限制解密的字节大小最多是128个。所以在此处采用分段解密,同时为了优化小程序首次的等待时间。只返回部分公钥,并且只有第一段公钥是加密的。这在很大程度上减少了等待的时间,让用户的体验更为流畅。
在这里将获取加密公钥的方法封账成一个Promise方法,是为了保证小程序进行编译的时候在app.js尚未执行完成的情况先,index.js中的方法进行先行调用时没有公钥的情况。

处理首次获取加密公钥失败的情况

//app.js
// 引入请求文件
const http = require('/server/request.js');
const sm2 = require('/server/sm2.js');
const api = require('/server/api.js');
const util = require('/utils/weapp.js');
App({
   
  globalData: {
   
    uuid: ''
  },
  onLaunch: function(e) {
   
    this.init();
    this.globalData.uuid = wx.getStorageSync('uuid');
    wx.clearStorageSync();
    wx.setStorageSync('uuid', this.globalData.uuid);
  },
  // 初始化
  async init() {
   
    await this.getPrivatekey(); // 请求数据
    this.getHomeSetting(); // 等待请求数据成功后
    this.checkUpdateVersion(); //更新版本号
  },
  // 获取系统设置
  getHomeSetting() {
   
    let that = this;
    http.requestLoading('api/services/app/CRMMemberService/GetHomeSetting', {
   }, 'GET').then(res => {
   
      
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值