Ajax跨域解决

1.何为跨域

  • AJAX跨域问题是指浏览器出于安全考虑,限制了一个源(域名、协议、端口)的脚本与另一个源的资源进行交互。通俗的说,当前页面的域名、协议、端口必须与ajax访问地址一致,才能正常通信,否则会造成跨域

2.解决方案

  • 浏览器开放限制:浏览器下载插件(Access-Control-Allow-Origin)
  • 代理服务器:在服务器端(前端所在服务器)设置一个代理服务器,所有AJAX跨域请求都发送到这个代理服务器,由代理服务器转发请求到目标服务器,并返回响应,相当于做了一个中转
  • CORS:服务器端(接口所在服务器)设置Access-Control-Allow-Origin响应头,允许特定的或所有域进行跨域请求
  • JSONP:通过 script 标签的src属性请求一个带参数的服务器端脚本,服务器端脚本输出一个指定函数的调用,该函数的参数是要传递的数据

3.Access-Control-Allow-Origin

  • 在chrome应用商店中搜 "cors",找到 "Access-Control-Allow-Origin"

  • 点击添加,安装完成后,启用该插件

4.CORS

  • http-server:启动时添加 --cors 参数,所有访问这个服务器的请求都允许跨域
http-server -c-1 -p 8097 --cors
  • express设置允许跨域
//引入express
const express = require("express")
//创建服务对象
let app = express()

app.all('*', function (req, res, next) {
    //跨域允许访问的域名(通配符表示所有域名皆可访问,多个域名用都好隔开)
    res.header("Access-Control-Allow-Origin",'*')
    //跨域允许的header包含哪些字段
    res.header("Access-Control-Allow-Headers","Content-Type,Authorization,X-Requested-With")
    //跨域允许的请求方式
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS")
    //执行下一步(跳转到下一个路由判断中)
    next()
})

//开启服务,监听80端口
var server = app.listen(80,function(){
    //当前当前监听的端口号
    var port = server.address().port
    console.log(`Server running at http://127.0.0.1:${port}/`)
})
  • 注意:如果当请求设置了 withCredentials 属性,服务器在响应头中设置 Access-Control-Allow-Origin 时不能使用通配符 *,而必须指定明确的域名

5.代理服务器

  • http-server:启动时添加 -P 或者 --proxy 参数,当前服务器不能解析的资源会转交到代理服务器
//启动页面服务器8096,接口代理至8097
http-server -c-1 -p 8096 -P http://127.0.0.1:8097

//接口服务器
http-server -c-1 -p 8097

//页面代码(先访问http://127.0.0.1:8096/data.json,无法解析后再代理至http://127.0.0.1:8097/data.json)
axios({url: "data.json"})

  • vue脚手架:配置方式不固定,一切以文档为主,代理配置
//vue.config.js

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
	transpileDependencies: true,
	lintOnSave: false,
	devServer: {
		//代理
		proxy: {
            // 匹配以/api开头的所有路径
			'/api': {  
				target: 'http://localhost:8097', // 代理的后端api域名
				changeOrigin: true, // 支持跨域
			}
		}
	}
})
<script>
    new Vue({
        el:"#app",
        data: {},
        created(){
            this.getMsg()
        },
        methods: {
            async getMsg(){
                try {
                    //接口一律访问当前8080服务器,然后自动代理至接口服务器,不得再访问原目标服务器
                    const result = await axios({
                        url: "/api/data.json",
                        //url: "http://127.0.0.1:8097/api/data2.json",//错误写法
                    })
                    console.log('success',result.data)
                } catch (error) {
                    console.log('error',error)
                }
            }
        }
    })
</script>

6.JSONP

  • 原理:前端利用script不受同源策略影响,动态插入一个script标签,script标签加载完毕后会立即执行里面的代码
  • 详细步骤:动态插入一个script标签并设定src地址(通过get参数告诉后端所需的接口参数和callbackFunction,callbackFunction要提前定义好),后端拿到此请求后,返回一段js代码,代码内容就是直接调用callbackFunction(),并传入数据,这样就完成了跨域请求,此种方法需要前后端同时配合
<script>
    function updatePage(obj){
        var h1 = document.querySelector("h1")
        var p = document.querySelector("p")
        h1.innerHTML = obj.title
        p.innerHTML = obj.content
    }
    //监听按钮点击
    $("#btn").on("click",function(){
        console.log("click")
        $.ajax({
            url:"./jsonp/index.js",
            type:"get",
            dataType: "jsonp",
            data:{
                id:1
            },
            jsonp:"cb",// 告诉后端,用那个字段名接口回调名称
            jsonpCallback:"updatePage",//回调名称
            success:function(data){
                console.log(data)
            }
        })
    })

  //运行代码会访问这个url
  //http://localhost:8080/jsonp/index.js?cb=updatePage&id=1
</script>
//后端代码 Node.js

//引入express
const express = require("express")
//创建服务对象
let app = express()


//设置路由,监听根路径的访问
app.get("/jsonp",function(req,res){
    //获取回调名称
    var jsoncallback = req.query.cb
    //要返回的数据
    var data = {title:"标题",content:"内容"}
    //拼接代码(执行js函数调用)
    var code = `${jsoncallback}(${JSON.stringify(data)})`
    //返回数据
    res.send(code)
})

//开启服务,监听80端口
var server = app.listen(8087,function(){
    
    //当前当前监听的端口号
    var port = server.address().port
    console.log(`Server running at http://127.0.0.1:${port}/`)
})
posted @ 2024-06-15 17:30  ---空白---  阅读(25)  评论(0编辑  收藏  举报