springboot跨域问题及其解决方案

weblog 精帖
4205

什么是跨域?

要了解跨域,先要说说同源策略。同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当页面在执行一个脚本时会检查访问的资源是否同源,如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

那么什么是跨域呢?

跨域,指的是从一个域名去请求另外一个域名的资源。即跨域名请求!跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。跨域的严格一点来说就是只要协议,域名,端口有任何一个的不同,就被当作是跨域。

案例

有两个项目testA和testB,testA对外提供接口,testB提供页面调用testA的接口。

TestA项目接口:
package com.example.demo.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("server")
public class TestController {
	
	@RequestMapping("test")
	public Map<String, Object> test(HttpServletResponse httpResponse,HttpSession session){
		System.out.println(session.getId());
		Map<String, Object> map=new HashMap<String, Object>();
		map.put("code",200);
		map.put("data",null);
		map.put("msg","成功");
		return map;
	}
}
testB项目页面 

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
测试
	<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
	<div id="msg">
	</div>
	<script type="text/javascript">
		$(document).ready(function(){
			$.ajax({
				url:'http://localhost:8090/server/test',
				type:'get',
				dataType:'json',
				success:function(res){
					console.log(res);
					$("#msg").html(res.msg);
				},
				error:function(){
					console.log("error");
				}
			})
		});
	</script>
	
</body>
</html>

在testB的页面中是用ajax调用了testA的接口
访问时会出现

进了error方法   

由于两项目的端口不通,所以造成了跨域访问                    

如何解决跨域问题?

其实解决跨域问题的方案很多,在此就介绍两种吧。

1.nginx代理

安装nginx代理服务器

配置文件中添加配置如下:

server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        location / { 
            proxy_pass http://localhost:8091;
			proxy_cookie_path / /;
			proxy_set_header Host                $host;
            proxy_set_header X-Real-IP           $remote_addr;
            proxy_set_header X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto   $scheme;
            proxy_redirect                       off;
        }
        location /server { #访问服务器路径
            rewrite  ^/apis/(.*)$ /$1 break;
            proxy_pass   http://localhost:8090;
			proxy_cookie_path /server /;
			proxy_set_header Host                $host;
            proxy_set_header X-Real-IP           $remote_addr;
            proxy_set_header X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto   $scheme;
            proxy_redirect                       off;
       }
	}

就本次测试而言
将/ server开头的请求转发到http://localhost:8090服务,
其他都转发到http://localhost:8091服务
此时服务器对外只暴露一个ip所有请求都通过nginx代理。

修改请求路径

$(document).ready(function(){
	$.ajax({
		url:'/server/test',
		type:'get',
		dataType:'json',
		success:function(res){
			console.log(res);
			$("#msg").html(res.msg);
		},
		error:function(){
			console.log("error");
		}
	})
});

修改:url:'/server/test',
修改后访问成功

跨域资源共享(CORS)

 其中在服务器端(testA项目)添加配置

package com.example.demo.controller;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@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;
	}
}

在前端页面(testB项目)设置

<script type="text/javascript">
	$(document).ready(function(){
		$.ajax({
			url:'http://localhost:8090/server/test',
			type:'get',
			dataType:'json',
			async:true,
		    xhrFields:{
			    ithCredentials:true
			},
			success:function(res){
				console.log(res);
				$("#msg").html(res.msg);
			},
			error:function(){
				console.log("error");
			}
		})
	});
</script>

其实就是加了

    async:true,
	xhrFields:{
         withCredentials:true
	},

添加了上述内容后访问成功

ss

但是上述两种方式虽然都解决了跨域问题,但是session却产生了冲突

这样的话用session保存回话状态就会失效。

原因是两个项目都会产生一个sessionid,存在cookie中传输到客户端,如果一个新的cookie与一个已存在的cookie的NAME、Domain和Path属性值均相同,则旧的cookie会被丢弃。

所以就会产生发送到本服务器的sessionid永远是另一个服务器产生的sessionid,而不能被本项目所识别。就会造成一直产生新的sessionid。

 

跨域如何解决session冲突?

其实对于springboot项目来说,解决此问题很简单
只需要在其中一个项目中配置如图:

server:
  port: 8090
  servlet:
    context-path: / 
    session: 
      timeout: 3600
      cookie: 
       name: sessionid

只要保证name不同即可。

此时两服务器上的sessionid就会各自保持一致。

猜你喜欢
  • blog 线程的同步

    多线程带来的: 线程有时候回和他线程共享一些资源,比如内存、数据库等。当多个线程同时读写同一份共享资源的时候,可能会发生冲突。这时候,我们就需要引入线程“同步”机制,即各位线程之间要有顺序使用,不能杂乱无章随意使用。实例
  • file 判断单链表是否有环以求环的入口和环长度2种分析-附java代码

    <pre class="language-java"><code class="line-numbers data-output match-braces rainbow-braces">/**
  • blog 数据结构和算法-判断单链表是否有环 求环的入口地址(java)

    :如上图的一个链表,如何判断一个链表中是否存在环,以如何求出环的入口以何如求出链表的长度。 一:利用hash表         首先准备一个hash表如hashMap等,然后从链表头部
  • blog springboot + thymeleaf样式引入和获取项目名称

    样式引入: <link rel='stylesheet' th:href='@{/layui/css/layui.css}'  media='all'> js引入: <script type='text/java
  • blog 配置nginx代理不同二级名访不同项目

    配置nginx代理不同二级名访不同项目 二级名a,访项目a server { listen 80; server_name a.jiajiajia.com; location / { p
  • blog 栈的应用-迷宫

    1.描述::上面有一个迷宫,灰色部分代表不能通过,白色部分代表可以通过,现在从a点出发,能否找到一条路径到达b点,如果能,输出此路径。下面采用试探法求,采用栈结构保存每一步的内容(包括坐标和向),每前进一步都进行四个向的试探,
  • blog springboot打包分离资源文件时遇到的

    多么痛的领悟~分离资源打包后运行项目,启动失败数据源初始化失败~检查,这种情况下没有打印错误日志,首先配置一下日志,将错误报告在控制台中打印出来。resources文件夹下 创建一个 log4j.properties 文件log4j.r
  • blog 阻塞队列原理

    1.什么是阻塞队列 阻塞队列是一个在队列基础上又支持了两个附加操作的队列。2.支持阻塞的插入法:队列满时,队列会阻塞插入元素的线程,直到队列不满。1.支持阻塞的移除法:队列空时,获取元素的线程会等待队列变为非空。2.阻塞队
  • ofc 最短路径-floyd算法(图的邻接矩阵表示)

    最短路径-floyd算法(图的邻接矩阵表示)
  • blog 关于父类和子类法发生重载的

      在一本书上看到过子类可以重载父类的法,关于这一点有点疑惑,个人重载是发生在同一个类中。网上关于这个也存在争议。先暂时作为一个记录在此   下面这张图片引用自《疯狂java讲义第三版》