美文网首页
封装axios,以及获取接口时解决签名重复的问题

封装axios,以及获取接口时解决签名重复的问题

作者: 北极星丶超帅的 | 来源:发表于2018-06-04 17:12 被阅读127次

    在获取接口时,总是提示签名重复,卡了两天,最后还是靠大神帮忙解决这个问题。

    我一开始就是直接给请求头部添加签名,但没注意到这样必不会每次生成不一样的echostr,下面是错误的代码:

    let access_key = 'xxx'; // 服务端生成的 access_key
    let secret_key = 'xxx'; // 服务端生成的 secret_key
    let headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      'api-access-key': access_key
    }
    
    function encrypting(secret_key, echostr, timestamp) {
      return md5(secret_key + echostr + timestamp); // md5 库自行引入
    }
    let timestamp = Date.now() / 1000;
    let echostr = randomWord(false, 8);
    
    axios.defaults.headers['api-timestamp'] = timestamp
    axios.defaults.headers['api-echostr'] = echostr
    axios.defaults.headers['api-signature'] = encrypting(secret_key, echostr, timestamp)
    axios.defaults.headers['Authorization'] = `Bearer ${token}`
    

    后来大神一眼就看出问题,下图是大神修改后的代码(封装axios是从网上找的,自己改了一些,还有一些其他问题的存在,建议如果需要使用,根据需要修改):

    'use strict'
    
    import qs from 'qs'
    import md5 from 'js-md5'
    import axios from "axios"
    import {
      randomWord
    } from './common'
    
    window.axios = axios;
    
    // 超时时间
    window.axios.defaults.timeout = 9000;
    
    // http request 拦截器
    window.axios.interceptors.request.use(config => {
      return config;
    }, err => {
      // TODO: 使用 UI 框架弹出错误
      console.error(err);
      return Promise.resolve(err);
    })
    
    // http response 拦截器  与后台提前定义正确code 错误的提示
    window.axios.interceptors.response.use(
      response => {
        if (response.data.code === 0) {
          return response
        } else if (response.config.responseType === 'blob') {
          return response
        } else {
          // TODO: 使用 UI 框架弹出错误
          console.error(response.data.msg)
          return Promise.reject(response)//Promise.reject(response)
        }
      },
      error => {
        if (error.response) {
          switch (error.response.status) {
            case 400:
              error.message = '请求错误(400)';
              break;
            case 401:
              error.message = '未授权,请重新登录(401)';
              break;
            case 403:
              error.message = '拒绝访问(403)';
              break;
            case 404:
              error.message = '请求出错(404)';
              break;
            case 408:
              error.message = '请求超时(408)';
              break;
            case 500:
              error.message = '服务器错误(500)';
              break;
            case 501:
              error.message = '服务未实现(501)';
              break;
            case 502:
              error.message = '网络错误(502)';
              break;
            case 503:
              error.message = '服务不可用(503)';
              break;
            case 504:
              error.message = '网络超时(504)';
              break;
            case 505:
              error.message = 'HTTP版本不受支持(505)';
              break;
          }
          console.log(error.response.status)
        } else {
          console.log(error)
        }
        return Promise.reject(error.response ? error.response.data : error)
      }
    )
    
    function checkStatus(response) {
      // loading
      // 如果http状态码正常,则直接返回数据
      if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {
        return response
        // 如果不需要除了data之外的数据,可以直接 return response.data
      }
      if (response && response.status === 401) {
        alert("登陆已过期,请重新登陆!")
      }
      // 异常状态下,把错误信息返回去
      return {
        status: 404,
        msg: '网络异常'
      }
    }
    
    function checkCode(res) {
      // 如果code异常(这里已经包括网络错误,服务器错误,后端抛出的错误),可以弹出一个错误提示,告诉用户
      // debugger
      if (res.status === 404) {
        console.log(res.msg)
      }
      if (res.data && (!res.data.success)) {
        console.log("code异常",res.data.code)
      }
      return res
    }
    
    let access_key = '服务端生成的 access_key'; // 服务端生成的 access_key
    let secret_key = '服务端生成的 secret_key'; // 服务端生成的 secret_key
    let headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
      'api-access-key': access_key
    }
    
    function encrypting(secret_key, echostr, timestamp) {
      return md5(secret_key + echostr + timestamp); // md5 库自行引入
    }
    
    
    
    // TODO: debug
    
    export function getDefaultHeaders() {
      let token = ''
      try {
        console.log("call mobile.getUserToken trying...")
        token = mobile.getUserToken();
        console.log("call mobile.getUserToken done ...", token)
      } catch (e) {}
      if (!token) {
        try {
          token = JSON.parse(sessionStorage.getItem("userInfo")).token;
        } catch (e) {}
      }
      if (!token) {
        try {
          token = JSON.parse(window.userInfoRaw).token;
        } catch(e) {}
      }
    
      let timestamp = Date.now() / 1000;
      let echostr = randomWord(false, 8);
      return Object.assign(headers, {
        'api-timestamp': timestamp,
        'api-echostr': echostr,
        'api-signature': encrypting(secret_key, echostr, timestamp),
        'Authorization': `Bearer ${token}`
      })
    }
    
    export default {
      get: (url, params) => {
        return window.axios({
          method: 'get',
          url,
          params, // get 请求时带的参数
          headers: getDefaultHeaders()
        }).then(
          (response) => {
            return checkStatus(response)
          }
        ).catch(
          (res) => {
            return checkCode(res)
          }
        )
      },
    
      post: (url, data, config = {}) => {
        return window.axios({
          method: 'post',
          url,
          data: qs.stringify(data),
          headers: Object.assign(getDefaultHeaders(), config.headers)
        }).then(
          (response) => {
            return checkStatus(response)
          }
        ).catch(
          (res) => {
            return checkCode(res)
          }
        )
      },
    
      upload: (url, data) => {
        return window.axios({
          method: 'post',
          url,
          data: data,
          headers: getDefaultHeaders()
        }).then(
          (response) => {
            return checkStatus(response)
          }
        ).catch(
          (res) => {
            return checkCode(res)
          }
        )
      },
    
      put: (url, params) => {
        return window.axios({
          method: 'put',
          url,
          data: qs.stringify(params),
          headers: getDefaultHeaders()
        }).then(
          (response) => {
            return checkStatus(response)
          }
        ).catch(
          (res) => {
            return checkCode(res)
          }
        )
      },
    
      delete: (url, params) => {
        return window.axios({
          method: 'delete',
          url,
          data: qs.stringify(params),
          headers: getDefaultHeaders()
        }).then(
          (response) => {
            return checkStatus(response)
          }
        ).catch(
          (res) => {
            return checkCode(res)
          }
        )
      }
    }
    

    使用封装方法

    //API.js
    
    import axios from 'axios'
    import http from './http'
    
    const host = '/xxx';
    
    //获取用户信息
    export function UserInfo(){
      let userInfo = window.sessionStorage.getItem('userInfo');
      try {
        userInfo = JSON.parse(userInfo);
      } catch (e) { 
        userInfo = null;
      }
        return userInfo;
    }
    
    
    //获取广告列表
    export function GetData(options) {     //在这里用options,方便按需加参数,当然也可以固定写死参数,看自己的需求
      const url = host + "/xxx";
      return http.get(url, options)
    }
    
    
    //index.vue
    <script>
    import { FindArticle } from 'api/articleList'
    export default {
      methods: {
          getData() {
             let options = {
                 id:xx,
                 type:xx
             }
             GetData(options).then(res => {}).catch(err=> {})
             }
          }
      }
    }
    </script>
    
    

    相关文章

      网友评论

          本文标题:封装axios,以及获取接口时解决签名重复的问题

          本文链接:https://www.haomeiwen.com/subject/coyysftx.html