关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求

0x01 实现步骤概述

技术栈:vue + node+es6+stylus
其中包含的库与模块:axioscrypto-jsrequestrouter
  • vue框架下前端页面编写
  • 本地axios网络请求,server端请求转发
  • 对网易云api加密进行分析,伪造,最后获取信息
  • 整体优化,防止请求错误导致server异常退出

0x02 vue框架下前端页面编写

1.目录结构
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第1张图片
image.png

目录结构是非常简单的,组件也非常少,一共有两个组件,

  • mHeader.vue组件是一个头组件,可以在这个组件放入logo或者一些标识,我这里放入的是一个纯色div
  • Search.vue组件是搜索组件,在这个组件内进行歌曲、歌手等搜索,也是我们着重编辑的部分
2.Router

为了以后添加更多的页面组件,这里我们采取router路由的方式来规划页面及页面间的跳转

export default new Router({
  routes: [
    {
      path: '/Search',
      name: 'Search',
      component: Search//引用Search页面
    },
    {
      path:'/',
      redirect:'/Search' //重定向,跳转到Search页面
    }
  ]
})
3.核心组件Search.vue
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第2张图片
image.png

页面很简单,主要是一个input框。现在我们希望在键入内容时,在下方弹出提示内容,像这样:


关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第3张图片
image.png

所以我们为input框绑定事件,方法有很多种,vue下可以便捷的使用这种方式


其中inputFun就是我们绑定的事件,每当input内容发生变化,就会执行这个函数。我们在methods中实现这个方法。
函数的具体实现:

methods:{
        inputFun(e){
          this.searchConent = e.target.value  //取出input内容
          console.log(this.searchConent)
          if(this.searchConent.length < 1){  //判断是否为空
            this.info_flag = false           //取消提示框的显示
            return
          }
          //执行查询
          this.searchSubmit(this.searchConent, () => {  //此时input不为空,执行查询函数,callback回调
            if (this.searchConent.length < 1){
              this.info_flag = false
              return
            }else{
              this.info_flag = true
            }
          })
        },
    ...//其他方法
  }

searchSubmit函数执行api查询,以下是searchSubmit函数注意这里需要使用callback回调,不然会出现问题,不使用callback回掉会造成提示框出现过早,我们希望请求到数据以后再进行显示

searchSubmit(data, callback) {
          search(data).then((res) => {
            if(res.data.code == "200"){
              this.searchInfoJson = res.data.result
              callback()
            }else{
              console.log('error:error')
            }
          })
        }

以上search.vue组件就算是写完了

0x03 本地axios网络请求,server端请求转发

1. server中间转发配置

vue在开发环境中调试时,本质就是启动了node服务器,再用这个node服务器去启动vue资源,那么我们的api请求代理转发就可以写在这个默认的node服务器,即在webpack.dev.conf.js中配置即可


关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第4张图片
image.png

这里我们需要在起始位置引入两个模块

//引入request模块
const request = require('request')

//引入APIenc加密模块
const enc = require('../API_ENC/enc.js')

其中request模块是一个http请求模块,使用它可以轻松的完成GET、POST等请求,我们用它来向网易云音乐获取数据。
enc模块是我们自己编写的加密模块,网易云api请求对数据进行了ASE、RSA加密,我们编写模块来重构数据加密。
devServer节点中建立before(app){},在这里面写http的get和post请求,并通过api的形式传回前端:

devServer: {
    //此处设置代理API
    before(app) {
      app.get('/api/test', (req, res) => {
        console.log(req.query.data)
        console.log('{"s":"'+req.query.data+'","limit":"8","csrf_token":""}')
        const h = enc.enc('{"s":"'+req.query.data+'","limit":"8","csrf_token":""}')
        const _data = 'params='+h.encText+'&encSecKey='+h.encSecKey
        //const _data='params=I9poLQX4QhYUqTlGJ0BuBqrBGfjgpwEOy91ZkftCJVKEh2fEs0EMzJOgYGDTmEyz4GAwdhdAeZ3L0oQU%2BCcmJEBODxiqBinxplaKGtUpfp8%3D&encSecKey=cc402fbec71e6483371fdfc6f7e14701f54b8d0b731617803436647fa1ca8db8e77236287d4be8b21336f04d527e10a7948b6da773d3a5de638b0005a194fc6c48fa6e5de32dcf891c388feec4c97ec4c6b3b6bd208c1389d6776d1cbc16425c9e15847bdb42257390030a5b2660ab6d1db81200d4458f9f6d9e6640b7393f16'
        console.log(_data)
        try{
          request.post({
            url:'https://music.163.com/weapi/search/suggest/web?csrf_token=',
            form:_data,
            headers:{
              'Content-Type':'application/x-www-form-urlencoded',
              'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
            }
          }, (error, response) => {
            if(response.body && response.body.length > 1){
              console.log(response.body)
              try{
                res.json({
                  error:0,
                  data:JSON.parse(response.body)
                })
              }catch (e) {
                console.log(e)
              }
            }else{
              console.log('数据空')
              res.json({
                error:0,
                data:{}
              })
            }
            //console.log(response.body)
          })
        }catch (e) {

        }
      }),
      app.post('/api/post', (req, res) => {
        res.json({
          errno: 0,
          data: 'helloPost'
        })
      })
    },
    //设置完毕
...其他代码  
}

其中的enc模块就是我们抽象的网易云音乐加密模块,在后面我们将详细着重介绍这个模块的编写

关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第5张图片
image.png

另外需要注意的是请求中的headers需要进行配置,否则将不能获取到数据,设置user-agent和content-type是爬虫和仿造请求的两个重要手段,在以后很多情况都要用到。

2. 前端axios请求api配置

当然还需要在前端配置api,其中我们使用了axios模块实现,将axios的get请求封装成search函数,并通过export进行暴露。

import axios from 'axios'

export function search (data) {
  const url = './api/test'
  console.log(data)
  return axios.get(url, {
    params: {
      data:data
    }
  }).then((res) => {
    console.log(res.data)
    return res.data
  })
}

之后,我们便可以在任何组件中轻松的使用这个api,
在search.vue组件中引入

import {search} from '../../api/httpReq'

0x04 对网易云api加密进行分析,伪造,最后获取信息

首先我们对网易云搜索提示的api进行分析,在输入内容前按下F12并转换到Network保持网络抓包开启

关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第6张图片
image.png

我们可以看到数据很多,点开最后一个,可以在preview中看到数据内容
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第7张图片
image.png

关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第8张图片
image.png

Headers可以看到提交的请求数据
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第9张图片
image.png

请求结构非常简单,但是data部分用到了加密,既然要伪造,那么就需要模拟加密过程,这里推荐大家使用fiddler,fiddler可以进行全局搜索,方便我们逆向加密算法,现在转到fiddler,刷新网易云页面,全局搜索encSecKey
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第10张图片
image.png

包含关键字的包将会被高亮显示
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第11张图片
image.png

这个包是很可疑的,这是一个js库,里面很可能就是加密算法,现在转到浏览器F12中的Source选项中打开这个js库
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第12张图片
image.png

这个按钮优化代码显示
image.png

定位到包含encSecKey的位置
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第13张图片
image.png

很明显,这个就是加密方法了,现在的主要问题是我们如何去提取这个方法到我们自己的模块。其实很简单,只要把加密过程走一遍分析他是什么类型的加密,这样我们再重构加密方法就易如反掌了。我们下一个断点看看具体参数。
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第14张图片
image.png

我们在12861行也就是函数头部下一个断点
image.png

断下来以后我们看到参数d就是被加密的原始数据,而剩下3个参数都是固定值,不发生变化,可以视之为盐。
image.png

这三个按钮分别是步过,步入,和执行到返回,善用调试,可以让问题变得简单。
我们一步一步跟下去,发现执行的顺序是
关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第15张图片
image.png

所以只要模拟a,b,c这三个函数即可

function a(a) {//主要是取随机生成盐
        var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
        for (d = 0; a > d; d += 1)
            e = Math.random() * b.length,
            e = Math.floor(e),
            c += b.charAt(e);
        return c
    }
    function b(a, b) {//数据进行AES加密
        var c = CryptoJS.enc.Utf8.parse(b)
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a)
          , f = CryptoJS.AES.encrypt(e, c, {
            iv: d,
            mode: CryptoJS.mode.CBC
        });
        return f.toString()
    }
    function c(a, b, c) {//盐进行RSA加密
        var d, e;
        return setMaxDigits(131),
        d = new RSAKeyPair(b,"",c),
        e = encryptedString(d, a)
    }
    function d(d, e, f, g) {
        var h = {}
          , i = a(16);
        return h.encText = b(d, g),
        h.encText = b(h.encText, i),
        h.encSecKey = c(i, e, f),
        h
    }

还原b方法可以直接用,不过需要注意引用Crypto-js库,这是一个专门的AES加密解密库。
而还原c方法则不可以直接复制了,因为这里的c方法并不是正常的RSA加密,详细的不同地方同学们可以深入调试,可以重新自己写c方法的加密,在这里不做过多介绍了,除了重写加密方法外,其实还有一种简单的方法,就是根据c函数的调用,找出对应得方法而依次调用,我这里也是采取了这种方法,直接从第12412行第12834行全部粘贴到我们的模块,经过测试这种方式是完全正确的。
所以整个enc模块看起来是这样的:

const CryptoJS = require('crypto-js')
function RSAKeyPair(a, b, c) {
  this.e = biFromHex(a),
    this.d = biFromHex(b),

//......此处省略复制的代码

lowBitMasks = new Array(0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535);
console.log('LOADING--------------------------------------------------------------------------')
function c(a, b, c) {
  var d, e;
  return setMaxDigits(131),
    d = new RSAKeyPair(b,"",c),
    e = encryptedString(d, a)
}
function a(a) {
  var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
  for (d = 0; a > d; d += 1)
    e = Math.random() * b.length,
      e = Math.floor(e),
      c += b.charAt(e);
  return c
}
function b(a, b) {
    var c = CryptoJS.enc.Utf8.parse(b),
    d = CryptoJS.enc.Utf8.parse("0102030405060708"),
    e = CryptoJS.enc.Utf8.parse(a),
    f = CryptoJS.AES.encrypt(e, c, {
        iv: d,
        mode: CryptoJS.mode.CBC
    });
    return f.toString()
}
function enc(data){
  var h = {}
  var i = a(16)
  h.encText = b(data, '0CoJUm6Qyw8W8jud')
  h.encText = b(h.encText, i)
  var e = '010001'
  var f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
  h.encSecKey = c(i, e, f);
  //console .log('encText:' + h.encText + '\n' + 'encSecKey:' + h.encSecKey)
  return h
}
/*
test:
APIenc('{"s":"周杰伦","limit":"8","csrf_token":""}')
*/
//console.log(enc('{"s":"周杰伦","limit":"8","csrf_token":""}'))
exports.enc = enc

到此,网易云api的加密分析就完成了,enc模块的编写也全部完成。

0x05 整体优化,防止请求错误导致server异常退出

1. server部分优化

在我测试的时候,会经常发生server异常崩溃死掉的情况,主要原因是请求的数据返回空,而我们想要将之解析为json格式,那么将会抛出一个解析格式不正确的错误。所以需要加之判断,判断请求数据是否为空,为空则返回空数据,不为空则进行解析。

if(response.body && response.body.length > 1){//数据不为空
              console.log(response.body)
              try{//尝试进行解析
                res.json({
                  error:0,
                  data:JSON.parse(response.body)
                })
              }catch (e) {
                console.log(e)
              }
            }else{
              console.log('数据空')
              res.json({
                error:0,
                data:{}
              })
            }
2. 前端优化

前端我们创建了一个info_flag标志位来规定是否对提示框进行显示,然而info_flag标志位的true false切换时机变得尤为重要,为了更好的用户体验,我们希望在生成数据以后进行提示框的现实,所以这里就用到了callback回调,在请求到数据以后进行回调,此时再进行标志位的切换。

searchSubmit(data, callback) {//获取数据函数
          search(data).then((res) => {
            if(res.data.code == "200"){
              this.searchInfoJson = res.data.result
              callback()//获取到数据以后再执行callback函数来显示info框
            }else{
              console.log('error:error')
            }
          })
        }

至此,所有的前端和server中间代理就完成了

cnpm run dev //使用此语句来运行吧!

0x06 效果演示

关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求_第16张图片
搜索演示.gif

点击github给个星星吧

你可能感兴趣的:(关于vue中间代理和ASE,RSA解密从而实现对网易云api的伪造请求)