2021-11-04

跨域问题及解决

跨域介绍

跨域问题是浏览器为了解决与安全相关的问题,而采用的同源策略。所谓同源:URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示它们同源。

产生原因

在这里插入图片描述
浏览器为了保证安全,在浏览器打开的a,b,c页签下划分a,b,c三个域。正常情况下,a.html带着自己的cookie只能访问a服务器,b.html带着自己的cookie只能访问b服务器,c.html带着自己的cookie只能访问c服务器。a不能访问b、c服务器,bc也是同样不能访问除自身外的其他两个域。如果a访问b服务器,则浏览器端会报如下图错误:
在这里插入图片描述

解决办法

跨域是发生在前后端交互的过程中,服务与服务之间交互不存在。如果我们硬是让a跨域访问b或c服务器怎么办,可以采取以下方法:

1. 添加响应头;在b或c后端服务方法返回时添加头响应头信息。

@RestController
public class HelloWorldController {
    @RequestMapping("/say")
    public String sayHello(HttpServletResponse response){
        response.addHeader("Access-Control-Allow-Origin","http://127.0.0.1:8080");
        return "Hello Spring Boot";
    }
}

注意:存在极少浏览器不支持;

2. java反向代理 ; 在a服务端做以下处理:
在配置文件添加

 	proxy.address=http://127.0.0.1:8081

在启动类注入RestTemplate

@SpringBootApplication
public class StApplication {

    public static void main(String[] args) {
        SpringApplication.run(StApplication.class, args);
    }

    @Autowired
    private RestTemplateBuilder builder;

    @Bean
    public RestTemplate restTemplate(){
        return builder.build();
    }
}

请求类中方法

@RestController
public class TestController {
    // 拦截代理地址
    @Value("${proxy.address}")
    private String proxyAddress;
    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/proxy/say")
    public Object proxyHello(HttpServletRequest request){
        // 处理掉代理地址中含有‘/proxy’
        String url = proxyAddress + request.getRequestURI().replace("/proxy","");
        return restTemplate.getForObject(url, Object.class);
    }
}

注意:受后台请求方式和返回类型的影响。当然也可以不用RestTemplate ,自己书写后端方法排除这个因素。
3. nginx反向代理 ; 常用的方法。在a.html直接访问nginx,nginx做代理访问b或c服务。
前段页面a.html配置如下

<script> 
	$("button").click(function () {
	    // 此处访问nginx
	    $.get("http://127.0.0.1:80/proxy/say",function(data){
	        console.log(data);
	    })
	}) 
</script>

在nginx的nginx.conf配置如下

location /proxy {
	rewrite ^/proxy/(.*)$ /$1 break; #正则:去掉请求中url中的第一个proxy标识。
    proxy_pass  http://127.0.0.1:8081;#请求b或c服务
           
   }

4. 利用spring boot 注解@CrossOrigin
直接在b或c服务方法上添加注解,只对该方法有效。

@RestController
public class HelloWorldController {
    @CrossOrigin
    @RequestMapping("/say")
    public Student proxyHello(HttpServletResponse response){
        Student student = new Student();
        student.setName("张三");
        return student;
    }
}

在b或c服务上添加配置类,对能够扫描到包下的方法有效。

@Configuration
public class CrosConfig {
	@Bean
	public CorsFilter corsFilter() {
		CorsConfiguration corsConfiguration = new CorsConfiguration();
		// 1,允许任何来源
		corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
		// 2,允许任何请求头
		corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
		// 3,允许任何方法
		corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
		// 4,允许凭证
		corsConfiguration.setAllowCredentials(true);
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", corsConfiguration);
		return new CorsFilter(source);
	}
}

5. 利用html中的本身的script标签
前端a.html中代码

<script>
function cross(data){
    console.log(data);
}
</script>
<script src="http://127.0.0.1:8081/cross"></script>

后端b或c服务代码

@RestController
public class HelloWorldController {
    @RequestMapping("/cross")
    public String cross(HttpServletResponse response){
        String str = "hello world";
        return "cross('"+ str +"');";
    }
}

注意:由于script 标签只支持post请求,所以该种方式对post请求有效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值