浏览器跨域问题及解决方法

219人浏览

1 浏览器跨域问题

跨域请求,是一个站点访问另外一个不同域名站点上的资源。当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。比如说通过<link>标签加载外部样式表文件、通过<img>标签加载外部图片、通过<script>标签加载外部脚本文件等。

同源策略(Same origin policy)是浏览器最基本的安全功能,同源策略阻止一个域的javascript脚本和另外一个域的内容进行交互(带src属性的标签不受同源策略限制)。默认情况下,脚本访问文档属性等数据采用的是同源策略。出于安全考虑,Firefox、Chrome等很多浏览器都不允许跨域请求。

2 解决方法——CORS(推荐)

2.1 CORS 跨域资源共享

CORS (Cross-Origin Resource Sharing)是一个W3标准,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持,CORS背后的基本思想,是使用HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。。实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信。CORS与JSONP的使用目的相同,但是比JSONP更强大。JSONP只支持GET请求,CORS支持所有类型的HTTP请求。

2.2 Java后端实现CORS跨域请求的方式

  • 使用注解 @CrossOrigin
  • 重写 WebMvcConfigurer
  • 返回新的CorsFilter
  • 手动设置响应头 (HttpServletResponse)
  • 自定web filter 实现跨域

无论哪种方案,最终目的都是修改响应头,向响应头中添加浏览器所要求的数据,进而实现跨域。

这里介绍Springboot常用的2种方法:

2.2.1 使用注解 (局部跨域)
在控制器类上使用注解 @CrossOrigin 表示该类的所有方法允许跨域。

@RestController
@CrossOrigin(origins = "*")
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "hello world";
    }

}

在方法上使用注解 @CrossOrigin:

@RestController
public class HelloController {

    @RequestMapping("/hello")
    @CrossOrigin(origins = "*")
     //@CrossOrigin(value = "http://localhost:8081") //指定具体ip允许跨域
    public String hello() {
        return "hello world";
    }

}

2.2.2 拦截器(全局跨域)

@Configuration
public class CORSConfig {
	
	@SuppressWarnings({ "rawtypes" })
	@Bean
	public FilterRegistrationBean corsFilter() {
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		CorsConfiguration config = new CorsConfiguration();
		config.setAllowCredentials(true);
		config.addAllowedOrigin("*");
		config.addAllowedHeader("*");
		config.addAllowedMethod("*");
		source.registerCorsConfiguration("/**", config); 
		FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
		bean.setOrder(0);
		return bean;
	}
	
}

 

3 其它跨域方法

  • JSONP
  • proxy
  • window.postMessage
  • window.name
  • document.domain
  • webSocket