java service/web前端解决跨域( CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.)

先给两个不从代码层面的解决方案,在客户端/服务器上安装 Nginx 代理软件 或者 Allow CORS: Access-Control-Allow-Origin 浏览器插件

1、什么是跨域?

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。

所谓同源是指,域名,协议,端口均相同,只要有一个不同,就是跨域。如:

http://www.123.com/index.html 调用 http://www.123.com/server.php (非跨域)

http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)

http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)

http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)

http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)

请注意:localhost127.0.0.1虽然都指向本机,但也属于跨域。

浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。

CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

2、跨域会阻止什么操作?

浏览器是从两个方面去做这个同源策略的,一是针对接口的请求,二是针对Dom的查询。

  • 1.阻止接口请求比较好理解,比如用ajax从http://192.168.100.150:8020/实验/jsonp.html页面向http://192.168.100.150:8081/zhxZone/webmana/dict/jsonp发起请求,由于两个url端口不同,所以属于跨域,在console打印台会报No 'Access-Control-Allow-Origin' header is present on the requested resource

值得说的是虽然浏览器禁止用户对请求返回数据的显示和操作,但浏览器确实是去请求了,如果服务器没有做限制的话会返回数据的,在调试模式的network中可以看到返回状态为200,且可看到返回数据

  • 2.阻止dom获取和操作

比如a页面中嵌入了iframesrc为不同源的b页面,则在a中无法操作b中的dom,也没有办法改变b中dom中的css样式。

而如果ab是同源的话是可以获取并操作的。

<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        iframe {
            width: 100%;
            height: 800px;
        }
    </style>
</head>
<body>
    <!--<iframe src="http://192.168.100.150:8081/zhxZone/webmana/attachment/imageManager" frameborder="0" id="iframe"></iframe>-->
    <iframe src="http://192.168.100.150:8020/实验/jsonp.html" frameborder="0" id="iframe"></iframe>
    <script type="text/javascript">
        var i = document.getElementById("iframe");
        i.onload = function () {
            /*console.log(i.contentDocument)
            console.log(i.contentWindow.document.getElementById("text").innerHTML)*/
            var b = i.contentWindow.document.getElementsByTagName("body")[0];
            i.contentWindow.document.getElementById("text").style.background = "gray";
            i.contentWindow.document.getElementById("text").innerHTML = "111";
        }
    </script>
</body>
</html>

甚至是可以获取iframe中的cookie

var i=document.getElementById("iframe");
i.onload=function(){
	console.log(i.contentDocument.cookie);
}

不用说也知道这是极为危险的,所以浏览器才会阻止非同源操作dom

浏览器的这个限制虽然不能保证完全安全,但是会增加攻击的困难性

虽然安全机制挺好,可以抵御坏人入侵,但有时我们自己需要跨域请求接口数据或者操作自己的dom,也被浏览器阻止了,所以就需要跨域。

跨域的前提肯定是你和服务器是一伙的,你可以控制服务器返回的数据,否则跨域是无法完成的 。

3、解决跨域

如果是前端的调试,推荐使用前端跨域插件 浏览器插件

一、服务器端

1.1、后端配置解决跨域 两种方式

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否.

这其实和第2中方法(后台配置)基本相同,都是通过过滤器在response中返回头部,使服务器和浏览器可互通。

Access-Control-Allow-Origin:指定授权访问的域
Access-Control-Allow-Methods:授权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)

f适合设置单一的(或全部)授权访问域,所有配置都是固定的,特简单。也没根据请求的类型做不同的处理

方式一:重写一个过滤器CORSFilter
@Component
public class CORSFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //只允许 http://localhost:9527 站点上的资源跨域
        //response.addHeader("Access-Control-Allow-Origin", "http://localhost:9527");
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.addHeader("Access-Control-Allow-Headers", "Content-Type");
        response.addHeader("Access-Control-Max-Age", "1800");//1800s == 30 min
        filterChain.doFilter(request, response);
    }
}

原因是请求中含有其他参数

解决:放行所有原始域

response.addHeader("Access-Control-Allow-Headers", "Content-Type"); 改为 response.addHeader("Access-Control-Allow-Headers", "*");

 //response.addHeader("Access-Control-Allow-Headers", "Content-Type");
 response.addHeader("Access-Control-Allow-Headers", "*");

或者

加上 Authorizationuserid

 response.setHeader("Access-Control-Allow-Headers", "Authorization");
 response.setHeader("Access-Control-Allow-Headers", "userid");

或者
在web请求的位置去掉这两个请求头参数

import mesConfig from '@/utils/globalConfig'
import axios from 'axios'
//本地请求对象
const localService = axios.create({
  baseURL: mesConfig.localURL
})
// axios.defaults.headers.common['Authorization'] = 'Bearer' + sessionStorage.getItem('access_token')
// axios.defaults.headers.common['userid'] = sessionStorage.getItem('id')
localService.interceptors.request.use(
  config => {
    return config
  },
  err => {
    return Promise.reject(err)
  }
)
方式二:springboot 配置注解
@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
          //放行哪些原始域
          config.addAllowedOrigin("*");
          //是否发送Cookie信息
          config.setAllowCredentials(true);
          //放行哪些原始域(请求方式)
          config.addAllowedMethod("*");
          //放行哪些原始域(头部信息)
          config.addAllowedHeader("*");
          //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
          config.addExposedHeader("*");

        //2.添加映射路径
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        //允许 所有 站点上的资源跨域
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}
方式三: 通过Nginx反向代理

上个方法跨域是借助了浏览器对 Access-Control-Allow-Origin 的支持。但有些浏览器是不支持的,所以这并非是最佳方案,现在我们来利用nginx 通过反向代理 满足浏览器的同源策略实现跨域!

这里是一个nginx启用COSR的参考配置

#
# Wide-open CORS config for nginx
#
location / {
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
     }
}

跨域问题_炎升的博客

springboot 解决跨域- SegmentFault 思否

解决跨域请求的问题【服务器端】 - 知乎

二、web前端

1、方法:

1.1、前端方法就用jsonp

使用JSONP主要是目的通过动态创建Script,动态拼接url,进而抓取数据,实现跨域。这篇文章主要介绍了VUE2.0Jsonp的使用方法(前端),需要的朋友可以参考下

jsonp是前端解决跨域最实用的方法。

原理就是html中 的link,href,src属性都是不受跨域影响的,link可以调用远程的css文件,href可以链接到随便的url上,图片的src可以随意引用图片,script的

本文作者:Journey&Flower

本文链接:https://www.cnblogs.com/JourneyOfFlower/p/16732251.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Journey&Flower  阅读(1068)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 Not Found REOL
404 Not Found - REOL
00:00 / 00:00
An audio error has occurred.

Fade away

Do over again

Fade away

Utai hajime no hitomojime

Itsumo mayotteru

Douse toritome no nai koto dakedo

Tsutawaranakya motto imi ga nai (Ooh-ooh, oh-oh-oh)

Doushitatte konna ni fukuzatsu nano ni

Kamikudaite yaranakya tsutawaranai

Hora kekkyoku kashi nanka dou datte ii

Boku no ongaku nanka kono yo ni nakutatte ii nda yo

Ii ndarou

Nee sou darou

Everybody don't know why

Everybody don't know much

Boku wa ki ni shinai, kimi wa kidzukanai

Doko ni mo mou inai inai

Everybody don't know why

Everybody don't know much

Wasureteiku, wasurerareteiku

We don't know, we don't know, no, no

Me no mae, hirogaru genjitsu sekai ga mata yuganda

Nando risetto shite mo

Boku wa boku igai no dareka ni wa umare kawarenai

Sonna no shitteru yo

Ki ni naru ano ko no uwasabanashi mo

Shinikaru hyouteki wa tsugi no sokuhou

Mahi shichatteru (Tteru) kokkara esukeepu (Keepu)

Tooku tooku made ikeru yo

Antei nante nai (Na-na-na-na)

Fuanteina sekai (Na-na-na-na)

Antei nante nai (Na-na-na-na)

Kitto ashita ni wa wasureru yo

Fade away

Do over again

Fade away

Souda sekai wa dokoka ga itsumo uso kusai

Kireigoto dake ja daijina hitotachi sura mamorenai

Kudaranai, bokura minna dokoka kurutteru mitai

Hontou no koto nanka zenbu kamisama mo shiranai

Kamisama mo shiranai (Woah, woah, woah, no, woah)

Kamisama mo shiranai (Woah, woah, woah, no, woah)

Kamisama mo shiranai, but

Kamisama mo shiranai (Woah, no, woah, no, woah)

Everybody don't know why

Everybody don't know much

Boku wa ki ni shinai, kimi wa kidzukanai

Doko ni mo mou inai inai

Everybody don't know why

Everybody don't know much

Wasureteiku, wasurerareteiku

We don't know, we don't know, oh, oh-oh-oh

Ahh, oh-oh-oh-oh

Woah, oh-oh-oh

Ooh, ooh, ooh, ooh-ooh-ooh-ooh