admin管理员组文章数量:1558076
一起探讨学习
每天给大家提供技术干货
博主技术笔记 https://notes.xiyankt
博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star https://gitee/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;
}
}
版权声明:本文标题:vue的axios在ie和苹果浏览器后端参数数据接收不到的问题 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1727374214a1111515.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论