likes
comments
collection
share

今日份,基础知识回顾--跨域

作者站长头像
站长
· 阅读数 13

1-跨域

什么是跨域?为什么使用同源策略?你有几种方法解决跨域问题?了解预检请求吗?

  • 因为浏览器出于安全考虑,有同源策略。也就是说,如果协议,域名或端口有一个不同就是跨域,Ajax请求就会失败。
  • 那么是出于什么安全考虑才会引入这种机制呢?其实主要是用来防止CSRF攻击的。简单来说,CSRF攻击是利用用户的登录状态发起恶意请求。
  • 也就是说,没有同源策略的情况下,A网站可以被任意其他来源的Ajax访问到内容。如果你当前A网站还存在登录状态,那么对方就可以通过ajax获取到你的任何信息,当然跨域并不能完全阻止CSRF。
  • 然后我们就来考虑一个问题,请求跨域了,那么请求到底发出去了没有?请求必然是发出去了,但是浏览器拦截了响应。你可能会疑问,明明通过表单的方式可以发起跨域请求,为什么AJAX就不会。因为:跨域是为了阻止用户督导另一个域名下的内容,ajax可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求,同时说明了跨域并不能完全阻止csrf,因为请求毕竟是发出去了。

总结学习一下几种常见的方式来解决跨域问题

1-jsonp

其原理很简单,就是利用

< script src= " http: / / domain/ api? param1 = a&  param2 = b& callback= jsonp" > < / script>
    
 <script>

function jsonp(data) {

console.log(data)

}

</script>
    

Jsonp 使用简单且兼容性不错,但是只限于get请求 在开发过程中可能遇到多个jsonp请求的回调函数名是相同的,这时候就需要自己封装一个jsonp,以下简单实现一下:

code.juejin.cn/pen/7235908…

2-CORS

  • cors需要浏览器和后端同时支持。

  • 浏览器会自动进行cors通信,实现cors通信的关键是后端,只要后端实现了cors,就实现了跨域。

  • 服务端设置Access-control-Allow-Origin就可以开启cors。改属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。虽然设置cors和前端没什么关系,但通过这种方式解决跨域问题的话,会在请求时出现两种情况,分别为简单请求和复杂请求。

简单请求:

以 Ajax 为例, 当满足以下条件时,会触发简单请求

  1. 使用下列方法之⼀:
  • GET
  • HEAD
  • POST
  1. Content-Type 的值仅限于下列三者之⼀:
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded
  • 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器;
  • XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问

复杂请求: 对于复杂请求来说, 首先会发起⼀个预检请求,该请求是 option 方法的。通过该请求来知道服务端是否允许跨域请求。

对于预检请求来说, 如果你使用过 Node 来设置 CORS 的话, 可能会遇到过这么⼀个坑。

以下以 express 框架举例

app.use(( req, res, next) => {
res.header( 'Access-Control-Allow-Origin', '*')
res.header( 'Access-Control-Allow-Methods', 'PUT, GET,        POST, DELETE, OPTIO
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization,

)

next()

})

该请求会验证你的 Authorization 字段,没有的话就会报错。

当前端发起了复杂请求后,你会发现就算你代码是正确的, 返回结果也永远是报错的 。因为预检请求也会进入回调中,也会触发 next 方法, 因为预检请求并不包含Authorization 字段,所以服务端会报错。

想解决这个问题很简单, 只需要在回调中过滤 option 方法即可

res.statusCode = 204
res.setHeader( 'Content-Length', '0')
res.end()      

2-模块化

涉及面试题:为什么要使用模块化?都有哪几种方式可以实现模块化,各有什么特点?
使用一个技术肯定是有原因的,那么使用模块化可以给我们带来什么好处:
  1.   解决命名冲突
    
  2.   提供复用性
    
  3.   提高代码可维护性
    

2.1 立即执行函数

在早期,使用立即执行函数实现模块化是常见的手段,通过函数作用域解决了命名冲突,污染全局作用域的问题。
    (function(globalVariable){

globalVariable.test = function() {}

// ... 声明各种变量 、函数都不会污染全局作用域

})(globalVariable)

2.2 AMD和CMD

鉴于目前这两种实现方式很少见,所以没必要具体细细讲解,只需要了解这两者是如何使用的。
    // AMD

define( [ './a', './b'], function(a, b) {

// 加载模块完毕可以使用

a.do()

b.do()

})

// CMD

define(function(require, exports, module) {

// 加载模块

// 可以把 require 写在函数体的任意地方实现延迟加载

var a = require( './a')

a.doSomething()

})

3-CommonJS

commonjs是最早的Node在使用,目前也仍然广泛使用,比如在webpack中你就能见到它,当然目前在node中的模块管理已经和commonjs有一些区别了。
// a.js

module.exports = {

a: 1

}

// or

exports.a = 1

// b.js
    var module = require( './a.js')

module.a // -> log 1

ar module = require( './a.js')

module.a

// 这里其实就是包装了⼀层立即执行函数, 这样就不会污染全局变量了,

// 重要的是 module 这里,module 是 Node 独有的⼀个变量

module.exports = {

a: 1

}

// module 基本实现

var module = {

id: 'xxxx', // 我总得知道怎么去找到他吧

exports: {} // exports 就是个空对象

}

// 这个是为什么 exports 和 module.exports 用法相似的原因

var exports = module.exports

var load = function (module) {

// 导出的东西

var a = 1

module.exports = a

return module.exports

};

// 然后当我 require 的时候去找到独特的

// id,然后将要使用的东西用立即执行函数包装下, over  

另外:虽然exports和module.exports用法相似,但是不能对exports直接赋值。因为var exports = module.exports这句代码表明了exports和modules.exports享有相同地址,通过改变对象的属性值会对两者都有效,但如果直接对exports赋值,会导致两者不再指向同一个内存地址修改并不会对module.exports生效。

4-ES Module

esmodule 是原生实现的模块化方案,与commonjs有以下几个区别:

  1. CommonJS 支持动态导⼊ ,也就是 require(${path}/xx.js) ,后者目前不支持,但是已有提案。
  2. CommonJS 是同步导⼊, 因为用于服务端,文件都在本地, 同步导⼊即使卡住主线程影响也不大 。而后者是异步导⼊,因为用于浏览器,需要下载文件,如果也采用同步导⼊会对渲染有很大影响。
  3. CommonJS 在导出时都是值拷贝,就算导出的值变了, 导入的值也不会改变,所以如果想更新值,必须重新导入⼀次 。但是 ES Module 采用实时绑定的方式, 导入导出的值都指向同⼀个内存地址,所以导入值会跟随导出值变化。
  4. ES Module 会编译成 require/exports 来执行的。
// 引入模块 API

import XXX from './a.js'

import { XXX } from './a.js'

// 导出模块 API

export function a() {}

export default function() {} 
转载自:https://juejin.cn/post/7235906062309982264
评论
请登录