接口请求跨域问题
跨域问题的本质
跨域问题源于浏览器的同源策略限制。同源策略要求协议、域名、端口三者完全相同才算同源。uni-app开发中,当应用请求不同源的接口时,浏览器会拦截响应数据。例如:
// 前端请求示例(会触发跨域)
uni.request({
url: 'https://api.other-domain.com/data',
success: (res) => {
console.log(res.data)
}
})
常见的解决方案
后端配置CORS
最规范的解决方式是在服务端设置Access-Control-Allow-Origin响应头:
// Spring Boot示例
@RestController
public class ApiController {
@GetMapping("/data")
public ResponseEntity<String> getData() {
HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Allow-Origin", "*");
return new ResponseEntity<>("response data", headers, HttpStatus.OK);
}
}
代理服务器方案
在uni-app项目中配置vue.config.js实现开发环境代理:
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://api.target.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
实际请求时使用相对路径:
uni.request({
url: '/api/userinfo', // 实际转发到https://api.target.com/userinfo
method: 'GET'
})
JSONP方案
适用于仅需GET请求的场景:
function jsonp(url, callbackName) {
return new Promise((resolve) => {
const script = document.createElement('script')
script.src = `${url}?callback=${callbackName}`
window[callbackName] = (data) => {
resolve(data)
document.body.removeChild(script)
delete window[callbackName]
}
document.body.appendChild(script)
})
}
// 使用示例
jsonp('https://api.example.com/data', 'handleData').then(data => {
console.log(data)
})
uni-app特有的解决方案
使用条件编译
针对不同平台采用不同方案:
// #ifdef H5
// 浏览器环境使用代理
const baseURL = '/api'
// #endif
// #ifdef MP-WEIXIN
// 小程序环境使用完整URL
const baseURL = 'https://api.weixin.com'
// #endif
uni.request({
url: baseURL + '/user/login'
})
配置manifest.json
对于微信小程序,需要在manifest.json中配置合法域名:
{
"mp-weixin": {
"appid": "",
"cloud": true,
"request": {
"domainWhiteList": [
"https://api.weixin.com"
]
}
}
}
生产环境部署方案
Nginx反向代理配置
server {
listen 80;
server_name yourdomain.com;
location /api/ {
proxy_pass https://api.backend.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
add_header Access-Control-Allow-Origin *;
}
}
云函数中转方案
通过uni-cloud云函数转发请求:
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
exports.main = async (event, context) => {
const res = await cloud.callFunction({
name: 'httpProxy',
data: {
url: 'https://api.target.com/data',
method: 'POST',
data: event.data
}
})
return res.result
}
调试技巧与注意事项
Chrome禁用安全策略
开发时临时禁用同源策略(仅限本地调试):
# MacOS
open -n -a "Google Chrome" --args --disable-web-security --user-data-dir=/tmp/chrome
错误处理示例
完善的错误处理机制:
uni.request({
url: 'https://api.example.com/data',
timeout: 8000,
fail: (err) => {
if (err.errMsg.includes('timeout')) {
uni.showToast({ title: '请求超时', icon: 'none' })
} else if (err.statusCode === 404) {
uni.showToast({ title: '接口不存在', icon: 'none' })
} else {
uni.showToast({ title: '网络错误', icon: 'none' })
}
}
})
特殊场景处理
文件上传跨域
需额外处理withCredentials:
uni.uploadFile({
url: 'https://api.example.com/upload',
filePath: tempFilePath,
name: 'file',
header: {
'Content-Type': 'multipart/form-data'
},
withCredentials: true // 需要携带cookie时设置
})
WebSocket跨域
WebSocket不受同源策略限制但受权限控制:
const socket = new WebSocket('wss://api.example.com/ws')
socket.onopen = () => {
console.log('连接成功')
socket.send(JSON.stringify({type: 'ping'}))
}
socket.onmessage = (e) => {
console.log('收到消息:', e.data)
}
安全相关建议
敏感信息保护
避免在前端硬编码敏感信息:
// 不推荐
const API_KEY = '123456abcdef'
// 推荐通过后端接口获取
uni.request({
url: '/getApiKey',
success: (res) => {
const key = res.data.key
// 使用获取到的key
}
})
HTTPS强制要求
现代浏览器对混合内容限制严格:
# 强制HTTPS
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益,请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:样式兼容性问题
下一篇:真机调试中的常见 Bug