一、什么是跨域

1‌、定义‌

跨域指的是从一个域名的网页去请求另一个域名的资源时,如果域名、端口、协议任一不同,都是跨域。在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。

同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同, 即便两个不同的域名指向同一个ip地址,也非同源。

2‌、原因‌

跨域是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。同源策略要求协议、域名、端口都要相同,其中有一个不同都会产生跨域。

3、影响‌

跨域限制访问是浏览器的限制,旨在防止恶意网站通过一个域的网页访问另一个域的敏感数据。没有同源策略,浏览器的许多功能可能无法正常工作。

‌4、示例‌

例如,a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,浏览器为了安全问题会限制这种访问‌

二、怎么解决跨域问题

1、前端

1.1 jsonp

ajax实现方式

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",  // 自定义回调函数名
    data: {}
});

 axios实现方式

this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

虽然jsonp可以实现跨域,但是因为jsonp不支持post请求,应用场景受到很大限制

1.2 代理

vue项目配置

changeOrigin: true
 
devServer: {
    host: '0.0.0.0',
    port: port,
    open: true,
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8080`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },

开发环境的跨域,也就是在vue-cli脚手架环境下开发启动服务时,我们访问接口所遇到的跨域问题,vue-cli为我们在本地开启了一个服务,可以通过这个服务帮我们代理请求,解决跨域问题。访问devServer 让devServer去访问服务器
vue-cli的配置文件即vue.config.js  
https://cli.vuejs.org/zh/config/#devserver-proxy 

module.exports = {
  devServer: {
   // 代理配置
    proxy: {
        // 这里的api 表示如果我们的请求地址有/api的时候,就出触发代理机制
        // localhost:8888/api/abc  => 代理给另一个服务器
        // 本地的前端  =》 本地的后端  =》 代理我们向另一个服务器发请求 (行得通)
        // 本地的前端  =》 另外一个服务器发请求 (跨域 行不通)
        '/api': {
        target: 'http://ihrm.itheima.net', // 我们要代理的地址
        changeOrigin: true, // 是否跨域 需要设置此值为true 才可以让本地服务代理我们发出请求
        }
    },
  }
}

2、后台(CORS)

2.1 单个控制器方法CORS注解

@RestController
@RequestMapping("/system/test")
public class TestController {
 
    @CrossOrigin
    @GetMapping("/{id}")
    public AjaxResult getUser(@PathVariable Integer userId) {
        // ...
    }
    
    @DeleteMapping("/{userId}")
    public AjaxResult delete(@PathVariable Integer userId) {
        // ...
    }
}

2.2 整个控制器启用CORS注解

@CrossOrigin(origins = "http://ruoyi.vip", maxAge = 3600)
@RestController
@RequestMapping("/system/test")
public class TestController {
 
    @GetMapping("/{id}")
    public AjaxResult getUser(@PathVariable Integer userId) {
        // ...
    }
    
    @DeleteMapping("/{userId}")
    public AjaxResult delete(@PathVariable Integer userId) {
        // ...
    }
}

2.3 全局CORS配置

/**
 * web跨域访问配置
 */
@Override
public void addCorsMappings(CorsRegistry registry)
{
    // 设置允许跨域的路径
    registry.addMapping("/**")
             // 设置允许跨域请求的域名
             .allowedOrigins("*")
             // 是否允许证书
             .allowCredentials(true)
             // 设置允许的方法
             .allowedMethods("GET", "POST", "DELETE", "PUT")
             // 设置允许的header属性
             .allowedHeaders("*")
             // 跨域允许时间
             .maxAge(3600);
}

3、代理

使用Nginx解决跨域,配置Nginx的反向代理

location / {  
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
 
    if ($request_method = 'OPTIONS') {
        return 204;
}
proxy_pass http://192.168.12.1:8081;
}

更多推荐