网络 浏览器同源策略、跨域、解决跨域(分享)

1. 同源策略

浏览器都有一个同源策略,同源策略是浏览器的一种安全策略,所谓同源是指协议、域名、端口完全相同,只有满足三者一致,才允许两个url地址之间做数据的交互

2. 跨域

当协议、域名(地址)、端口只要有一个不相同时就会跨域

3. 解决跨域

这里使用 gulp 模拟的前端服务,端口号8080,配置代码不重要主要是进行压缩,配置代码不需要看,需要注意的是,前端服务端口号8080,后端服务端口号9527就会进行跨域

注意:其实使用 vscode 就可以开启一个端口为5050的热加载,也就是说可以不使用 gulp 开启一个服务,但是在前端解决跨域需要在配置文件里代理,所以就把配置文件一起发出来了(gulp 配置文件里都有注释)

// src:入口文件
// dest:出口文件
// series:组合任务
// parallel:并行任务
// watch:观察文件变化
const { src, dest, series, parallel, watch } = require("gulp")

// 删除文件
const del = require("del")

// html代码压缩
const htmlmin = require("gulp-htmlmin")


// css处理
// less转css
const less = require("gulp-less")
// sass转css
const sass = require("gulp-sass")(require("sass"))
// css压缩
const csso = require("gulp-csso")

// js处理
// js代码压缩
const uglify = require("gulp-uglify")
// ES6转换
const babel = require("gulp-babel")

// 热更新
const connect = require("gulp-connect")

// 处理 HTML 模板
const fileinclude = require('gulp-file-include');

// 代理
const { createProxyMiddleware } = require('http-proxy-middleware')

// html 文件处理
function html() {
  // 入口文件路径
  // .pipe 输送给下一个任务
  return src("./src/*.html")
    // html模板处理
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    // html 压缩
    .pipe(htmlmin({ collapseWhitespace: true }))
    // 出口文件路径
    .pipe(dest("./dist"))
    //每次改变代码自动更新
    .pipe(connect.reload())
}

// css 文件处理
function css() {
  return src(["./src/css/*.less", "./src/css/*.scss", "./src/css/*.css"])
    // less转css
    .pipe(less())
    // sass转css
    .pipe(sass().on("error", sass.logError))
    // css压缩
    .pipe(csso())
    .pipe(dest("./dist/css"))
    .pipe(connect.reload())
}

// js 文件处理
function js() {
  return src("./src/js/*.js")
    // ES6转换
    .pipe(babel({
      presets: ["@babel/env"]
    }))
    // 进行压缩
    .pipe(uglify())
    .pipe((dest("./dist/js")))
    .pipe(connect.reload())
}

// img 文件处理
function img() {
  return src("./src/img/**")
    .pipe(dest("./dist/img"))
    .pipe(connect.reload())
}

// 清空dist下的所有文件
function clear() {
  return del(["./dist/**"]).then(() => {
    console.log("文件已清空");
  }).catch(() => {
    console.log("文件清空失败");
  })
}

// 热加载
function server() {
  connect.server({
    name: "dev",
    // 地址
    host: "localhost",
    // 端口
    port: "8080",
    // 观察哪个文件
    root: "./dist",
    // 热更新
    livereload: true
  })
}

// 观察文件变化
function watchList() {
  watch("./src/*.html", series(html))
  watch("./src/css/*.css", series(css))
  watch("./src/css/*.less", series(css))
  watch("./src/css/*.scss", series(css))
  watch("./src/js/*.js", series(js))
  watch("./src/img/**", series(img))
}

function init() {
  return [html, css, js, img]
}

// 打包
exports.build = parallel(clear, series(...init()))

// server
exports.server = series(clear, series(...init()), parallel(server, watchList))

这里使用 node 模拟的服务器(后端服务),端口号9527

// 使用 express 框架
const express = require("express")

const app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.get("/login", (request, response) => {
  response.send()
})

app.post("/login", (request, response) => {
  response.send()
})

app.listen("9527", () => {
  console.log("服务已开启: http://127.0.0.1:9527");
})
3.1 前端解决
  • 配置前端服务器代理,转发到后端服务器
    // gulp 配置文件
    // 进行代理
    const apiProxy = createProxyMiddleware("/api", { // 在配置文件中,监听的是前端的地址
      // 通过代理转发,到后端获取数据,在传给前端
      target: 'http://127.0.0.1:9527', // 目标地址
      changeOrigin: true, // 需要进行代理
      pathRewrite: { // 重写路径
        '^/api': '',
      }
    })
    
    // 热加载
    function server() {
      connect.server({
        name: "dev",
        // 地址
        host: "localhost",
        // 端口
        port: "8080",
        // 观察哪个文件
        root: "./dist",
        // 热更新
        livereload: true,
        middleware() {
          return [apiProxy]
        }
      })
    }
    
    // 前端请求部分,这一点要注意,要请求前端的地址,然后路径中间拼 api
    // html结构是使用下面 jsonp 的
    // 前端地址
    const baseUrl = "http://localhost:8080"
    
    let username;
      
    let password;
      
    document.querySelector("button").addEventListener("click", function () {
      username = document.querySelector("#username").value
      password = document.querySelector("#password").value
      
      fetch(baseUrl + "/api/login", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({ username, password })
      }).then(res => {
        return res.json()
      }).then(data => {
        console.log("data:", data);
      }).catch(err => {
        console.log("err:", err);
      })
    })
    
3.2 后端解决
  • 配置响应头允许跨域
    // 后端服务部分
    // 服务端解决跨域 cors,这种不太安全
    app.all('*', (req, res, next) => {
      res.header("Access-Control-Allow-Origin", "*"); // 允许任何地址跨域
      res.header("Access-Control-Allow-Headers", "*"); // 允许任何请求数据格式通过
      next();
    });
    

    注意:这个时候要注意,直接访问后端服务的地址就可以了

    3.3 前后端解决
  • jsonp,利用 script 标签处理
    <!-- html部分 -->
    <label for="username">
      账号:
    </label>
    <input type="text" id="username">
    
    <label for="password">
      密码:
    </label>
    <input type="password" id="password">
    
    <button>登录</button>
    
    // js部分
    // 服务端地址
    const baseUrl = "http://127.0.0.1:9527"
    let username;
    let password;
    
    // 后端传过来数据时,会执行这个函数,可以在这个函数中处理数据
    function login(params) {
      console.log(params);
    }
    document.querySelector("button").addEventListener("click", function () {
      username = document.querySelector("#username").value
      password = document.querySelector("#password").value
      
      // 点击时动态添加 script 标签,首先 script标签 为 GET 请求,而且不受跨域影响
      // 所以用 script 标签代替我们发送 get 请求
      let script = document.createElement("script")
      script.src = baseUrl + `/login?username=${username}&password=${password}`
      document.body.appendChild(script)
    })
    
    // nodejs 部分
    app.get("/login", (request, response) => {
      // 后端响应一个 login({key:value})的代码,它会执行这个代码就会找前端中的 login 函数
      // 这样就可以前后端一起解决跨域了
      response.send(`login(${JSON.stringify(request.query)})`)
    })
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Uniapp 是一个跨平台的应用开发框架,可以将一个应用同时打包成 H5、小程序和 APP 等多个平台。在将 Uniapp 应用运行到浏览器时,由于浏览器同源策略,可能会遇到跨域问题。那么如何解决呢?以下是几种可能的解决方案。 1. 在后台设置跨域请求头。如果 Uniapp 应用需要访问后台接口,可以在后台服务器上设置响应头,允许来自特定域名的跨域请求。例如,在 PHP 后台可以添加以下代码: ``` header('Access-Control-Allow-Origin: http://yourdomain.com'); ``` 其中 `yourdomain.com` 是允许跨域请求的域名。 2. 使用代理服务器。在开发环境下,可以使用代理服务器来绕过同源策略。比如,使用 `http-proxy-middleware` 做代理,将需要跨域请求的接口代理到同域下的接口。这样,在本地开启的服务器就可以访问后台接口了。 3. 在 config 文件夹下的 index.js 中设置反向代理。根据需要进行配置,通过修改 proxyTable 将目标服务器的地址和端口指向本地的代理服务器,从而实现跨域。例如: ``` proxyTable: { '/api': { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/api': '' } } } ``` 其中,`/api` 是需要反向代理的路径,`target` 是目标服务器的 IP 和端口,`changeOrigin` 设置为 `true` 表示修改请求头,将主机名设置为目标服务器的地址,`pathRewrite` 用于重写路径。 4. 使用 JSONP。如果后台接口可以返回 JSONP 格式的响应,可以在前端通过动态插入script 标签的方式实现跨域请求。 以上是几种可能的解决方案,根据实际情况选择合适的方法即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值