vue的axios在ie和苹果浏览器后端参数数据接收不到的问题

一起探讨学习

欢迎大家进群,一起讨论学习

每天给大家提供技术干货

在这里插入图片描述

博主技术笔记 https://notes.xiyankt.com


博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star https://gitee.com/bright-boy/xiyan-blog


vue的axios在ie和苹果浏览器后端参数数据接收不到的问题

ie和苹果手机的浏览器通过axios请求后端接口,后端获取不到的原因是,ie和苹果的浏览器支持Content-type是 application/x-www-form-urlencoded 所以你需要在请求修改Content-type为application/x-www-form-urlencoded

request.js

import axios from 'axios'
import Cookies from "js-cookie";
import {
    Message,
} from 'element-ui'
import store from '../store'
import {
    getToken,
    getAes,
} from '@/utils/auth'
import {
    AESDecrypt
} from '@/api/aes'
// 创建axios实例
const service = axios.create({
    baseURL: process.env.BASE_API, // api的base_url
    timeout: 600000 // 请求超时时间
})

// request拦截器
service.interceptors.request.use(config => {
    //获取登录成功后store中的token
    if (store.getters.token) {
        //如果有toekn才携带请求头中的token到后端
        config.headers['x-access-token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    //由于在没有登录之前需要对后端提示做国际化,所以就去掉了token的验证,让每个请求携带语言标识
    config.headers['x-access-language'] = Cookies.get('locale')
        //官网只查询上线的数据
    config.headers['x-line'] = "0"
        //兼容ie和苹果手机的浏览器,默认是不支持appliction/json方式
    config.headers['Content-type'] = "application/x-www-form-urlencoded"
    return config
}, error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
})

// respone拦截器
service.interceptors.response.use(
    response => {
        /**
         * code为非200是抛错 可结合自己业务进行修改
         */
        var res;
        //判断服务器返回是否是加密数据
        if (response.data.responseData != null && response.data.responseData != "") {
            //进行解密数据
            let aesDecrypt = AESDecrypt(response.data.responseData, getAes());
            //解密后转换成json
            res = JSON.parse(aesDecrypt);
        } else {
            //不是加密的数据正常返回
            res = response.data
        }
        if (!res.success) {
            //登录失败我需要自己自定义错误,所以这里就不需要帮我弹框出来
            if (res.errorCode === "-302") {
                return Promise.reject('error');
            }

            //这里的意思除了就是状态码为E0707不需要它帮我打印出错误信息,我自己定义,其它都进行打印
            if (res.errorCode === "E0707" || res.errorCode === "E0706") {
                return res
            }
            //如果客户端密钥已经失效提示用户重新登录或者最新的密钥
            if (res.errorCode === "E0708" || res.errorCode === 'E0701') {
                alert(res.errorCode)
                store.dispatch('FedLogOut').then(() => {
                    location.reload() // 为了重新实例化vue-router对象 避免bug
                })
                return;
            }

            Message({
                message: res.errorMsg,
                type: 'error',
                duration: 3 * 1000
            })
            return Promise.reject('error')
        } else {
            return res
        }
    },
    error => {
        //如果客户端密钥已经失效或者token失效提示用户重新登录
        if (error.response.status === 678) {
            store.dispatch('FedLogOut').then(() => {
                location.reload() // 为了重新实例化vue-router对象 避免bug
            })
            return Promise.reject(error);
        }
        if (error.response.status == 401) {
            location.href = "/login";
            return Promise.reject(error)
        }
        console.log('err' + error) // for debug
        Message({
            message: error.message,
            type: 'error',
            duration: 3 * 1000
        })
        return Promise.reject(error)
    }
)

export default service

后端修改,我用的框架是SpringCloud Alibaba,网关修改如下

package com.yoostar.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.yoostar.gateway.constants.Constant;
import com.yoostar.gateway.util.AESUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.cloud.gateway.support.DefaultServerRequest;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;


/**
 * 处理前端请求体解密和
 *
 * @author bright
 * @date 2020-09-18
 */
@Component
@Slf4j
public class RequestBodyFilter implements GlobalFilter, Ordered {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取aes密钥
        String keypair = redisTemplate.opsForValue().get(Constant.AES_KEY);
        log.info("redis-key [{}]", keypair);
        //获取ServerHttpRequest对象
        ServerHttpRequest request = exchange.getRequest();

        //根据请求头的x-aes 判断请求参数是否需要加密
        HttpHeaders head = request.getHeaders();
        String encryptionFlag = head.getFirst("x-aes");
        if (encryptionFlag != null) {
            if (encryptionFlag.equals(Constant.ENCRYPTION_FLAG)) {
                return chain.filter(exchange);
            }
        }

        //获取请求类型
        String methodValue = request.getMethodValue();
        //获取Content-type
        String contentType = head.getFirst("Content-type");
        log.info("requestUrl [{}], Content-type [{}],  method [{}]", request.getURI(), contentType, methodValue);
        //获取请求体
        Object requestBody = exchange.getAttribute("cachedRequestBodyObject");
        String requestData = "";
        //PUT请求Content-type可以是application/json,application/json;charset=utf-8,application/x-www-form-urlencoded
        if (methodValue.equalsIgnoreCase(HttpMethod.PUT.toString())) {
            requestData = InterceptFormData(requestBody);
        } else {
            //如果是post请求的看 Content-type 为application/x-www-form-urlencoded还是application/json类型
            if (null != contentType) {
                //Content-type不同数据解密方式不同,需要做特殊处理
                // 兼容ie和苹果手机的浏览器,默认是不支持application/json方式
                if (contentType.equalsIgnoreCase(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
                    requestData = InterceptFormData(requestBody);
                } else {
                    requestData = InterceptPost(requestBody, request);
                }
            }
        }
        log.info("\n 加密串》requestBody[{}]", requestData);
        if (!requestData.equals("")) {
            //获取解密后的内容
            String content = AESUtil.aesDecrypt(requestData, keypair);
            log.info("\n 解密后》requestBody[{}]", content);
            // mediaType
            MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
            // read & modify body
            ServerRequest serverRequest = new DefaultServerRequest(exchange);
            Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
                    .flatMap(body -> {
                        if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)) {
                            // 对原先的body进行修改操作
                            return Mono.just(content);
                        }
                        return Mono.empty();
                    });
            BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
            HttpHeaders headers = new HttpHeaders();
            headers.putAll(exchange.getRequest().getHeaders());
            headers.remove(HttpHeaders.CONTENT_LENGTH);
            /*由于Content-type为application/x-www-form-urlencoded的时候 后端@requestBody获取不到参数
            所以这里需要修改CONTENT_TYPE为 application/json
                    《删除 CONTENT_TYPE》
            */
            headers.remove(HttpHeaders.CONTENT_TYPE);
            CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
            return bodyInserter.insert(outputMessage, new BodyInserterContext())
                    .then(Mono.defer(() -> {
                        ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
                                exchange.getRequest()) {
                            @Override
                            public HttpHeaders getHeaders() {
                                long contentLength = headers.getContentLength();
                                HttpHeaders httpHeaders = new HttpHeaders();
                                httpHeaders.putAll(super.getHeaders());
                                if (contentLength > 0) {
                                    httpHeaders.setContentLength(contentLength);
                                } else {
                                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                                }
                                //重新设置CONTENT_TYPE为 application/json
                                httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                                return httpHeaders;
                            }

                            @Override
                            public Flux<DataBuffer> getBody() {
                                return outputMessage.getBody();
                            }
                        };
                        return chain.filter(exchange.mutate().request(decorator).build());
                    }));
        }
        return chain.filter(exchange);
    }


    /**
     * 如果是post请求的只能是 Content-type 为application/x-www-form-urlencoded
     * 如果是PUT请求可以是application/json,application/json;charset=utf-8,application/x-www-form-urlencoded
     * 三种类型
     *
     * @param requestData
     * @return
     */
    public String InterceptFormData(Object requestData) {
        if (requestData != null && !requestData.equals("")) {
            String s = "{\"requestData\":";
            if (!requestData.toString().startsWith(s)) {
                throw new RuntimeException("参数【requestData】缺失异常!");
            } else {
                int closeLen = requestData.toString().length() - 1;
                int openLen = "{\"requestData\":".length();
                String substring = StringUtils.substring(requestData.toString(), openLen, closeLen);
                return substring;
            }
        }
        return "";
    }

    /**
     * 截取POST请求body的加密数据
     * 这是  Content-type 为 application/json或者
     * application/json;charset=utf-8类型 才可以
     *
     * @param requestBody
     * @param request
     * @return
     */
    public String InterceptPost(Object requestBody, ServerHttpRequest request) {
        //过滤一些请求,因为支付的回调里面的参数是没有加密的所以转换会出现问题,所以需要过滤下支付的回调地址
        if (request.getURI().toString().indexOf("/member/paypal/ipn/back") != -1
                || request.getURI().toString().indexOf("/member/dlocal/back") != -1
                || request.getURI().toString().indexOf("/member/dlocal/cancel") != -1
        ) {
            return "";
        }
        //将请求体json对象转换为JSONObject
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(requestBody);
        //获取加密串
        String requestData = "";
        if (requestBody != null) {
            requestData = jsonObject.get("requestData").toString();
        }
        return requestData;
    }

    @Override
    public int getOrder() {
        return -2;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘明同学呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值