admin管理员组

文章数量:1529463

一、什么是同源策略

       同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。同源策略是一种关键的安全机制,它限制一个源加载的文档或脚本如何与另一个源的资源进行交互。

       同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。

       当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

       同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

二、为什么需要跨域

       为了满足从域名A下的一个页面(一般ajax或CORS请求等)获取域名B下的一个资源,但是浏览器的同源策略的限制默认并不允许这样的事情发生,所以需要跨域。

三、什么情况下会出现跨域

       1、跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/java......等其它环境。

       2、跨域请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。

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

四、如何跨域/绕开跨域

       1、设置Access-Control-Allow-Origin

       2、JsonP、CORS、反向代理等。

五、设置Access-Control-Allow-Origin的意义

       如果不需要让其它网站可以跨域访问我们的资源,可以不设置。

       需要让其它网站可以跨域访问,则必须设置。 

       但是这时就不建议设置*了,而是设置指定的域名(Access-Control-Allow-Origin:域名),毕竟我们不想谁都可以随意访问我们的资源。

       设置了Access-Control-Allow-Origin:域名,并不能避免别人用非跨域的方式直接访问,但是这个问题就涉及到API接口安全性的问题了。

六、spring boot跨域设置

1、spring boot设置

        SpringBoot可以基于Cors解决跨域问题,我们创建一个全局配置文件。

package com.home.skydance.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * SpringBoot可以基于Cors解决跨域问题,
 * Cors是一种机制,设置那些请求可以访问服务器的数据。
 */
@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            // 重写父类提供的跨域请求处理的接口
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                // 添加映射路径
                registry.addMapping("/**")
                        .allowedOriginPatterns("*")                         // 放行哪些域名,可以多个
                        .allowCredentials(true)                             // 是否发送Cookie信息
                        .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") // 放行哪些请求方式
                        .allowedHeaders("*")                                // 放行哪些原始域(头部信息)
                        .exposedHeaders("Header1", "Header2")               // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
                        .maxAge(3600);                                      // 预请求的结果有效期,默认1800分钟,3600是一小时
            }
        };
    }
}

2、创建接口

@GetMapping("/resttemplate-blocking")
public List<String> getResttemplateBlocking() {
    log.info("请求开始");
    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<List<String>> response = restTemplate.exchange(
            url, HttpMethod.GET, null,
            new ParameterizedTypeReference<List<String>>(){});
    List<String> result = response.getBody();
    log.info("请求完成");
    return result;
}

3、使用jquery调用

<html>
<head>
<script src="http://ajax.googleapis/ajax/libs/jquery/1.8.0/jquery.min.js">
</script>

<script>
	$.get("http://127.0.0.1:9001/resttemplate-blocking",function(data,status){
		alert("Data: " + data + "\nStatus: " + status);
	});
</script>
</head>
</html>

        spring boot禁止跨域时,显示如下错误

Access to XMLHttpRequest at 'http://127.0.0.1:9001/resttemplate-blocking' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

         设置跨域之后,获得相应结果。

4、使用CORS调用

        同样spring boot未设置跨域时调用失败会说“Access-Control-Allow-Origin”的错误,spring boot设置之后会再浏览器打印返回的数据。

<html>
<head>
<script>    
const xhr = new XMLHttpRequest;    
// true 开启异步    
xhr.open("GET","http://127.0.0.1:9001/resttemplate-blocking",true);    
xhr.onreadystatechange = ()=>{        
	if(xhr.readyState === 4){            
		if(200 <= xhr.status && xhr.status < 300 || xhr.status === 304){                
			console.log(xhr.response);            
		}        
	}    
}    
xhr.send()
</script>
</head>
</html>

5、使用Fetch API

        Fetch API fetch api是一个基于Promiseapi设计的xmlHttpRequest的升级替代品,用于通过javascript发起异步请求。

<html>
<head>
<script>    
fetch('http://127.0.0.1:9001/resttemplate-blocking').then(function(data){
      // text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
      return data.text();
    }).then(function(data){
      //在这个then里面我们能拿到最终的数据  
      console.log(data);
    })
</script>
</head>
</html>

七、小结

        类似上面前端进行请求的库还有一些,比如Axios、SuperAgent等,但是殊途同归,跨域的问题只要后端设置好,或者干脆用反向代理解决。

        以上代码

java_example/crossdomain at main · bashendixie/java_example · GitHubContribute to bashendixie/java_example development by creating an account on GitHub.https://github/bashendixie/java_example/tree/main/crossdomain

本文标签: 示例详解浏览器策略Java