五种网站跨域问题解决方案

一、什么是跨域问题

        是两个项目之间使用ajax(前端类似与后端技术httpclient)实现通讯,如果浏览器访问的域名地址和端口号与ajax访问的地址和端口号不一致的情况下,默认情况下浏览器会有安全机制,这个机制就是跨域问题,会造成无法获取到返回结果(但实际还是可以访问的,请求状态码为200,但无法获取到结果)。

二、跨域问题怎么解决:

跨域问题有如下5中解决方案:

1、使用jsonp解决 跨域问题(不推荐,因为只能支持get请求,不支持post请求)
2、使用httpclient进行转发(不推荐,因为效率非常低,会发送两次请求)
3、设置响应头允许跨域(可以推荐)适合于小公司快速解决问题
4、使用Nginx搭建API接口网关(强烈推荐)因为保证域名和端口都一致,以项目区分反向代理到真实服务器地址。
5、使用Zuul微服务搭建API接口网关(强烈推荐)SpringCloud

网站跨域问题演示:

新建两个maven项目(xwhy_web_a,xwhy_web_b),pom类型为war类型。

pom依赖

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
	</parent>
	<dependencies>
		<!-- SpringBoot 对lombok 支持 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<!-- SpringBoot web 核心组件 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
		</dependency>
		<!-- SpringBoot 外部tomcat支持 -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<!-- springboot-log4j -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j</artifactId>
			<version>1.3.8.RELEASE</version>
		</dependency>
		<!-- springboot-aop 技术 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
	</dependencies>

application.yml (a项目端口号为8080,b项目端口号为8081)

server:
  port: 8080
spring:
  mvc:
    view:
      prefix: /WEB-INF/jsp/
      suffix: .jsp

在b项目中新建BIndexController.java类

@RestController
@SpringBootApplication
public class BIndexController {

	// 该接口提供给A项目进行ajax调用
	@RequestMapping("/getBInfo")
	public Map<String, Object> getBInfo() {
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("retCode", "200");
		result.put("retMsg", "登陆成功");
		return result;
	}

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

}

在a项目中新建AIndexController.java类

@Controller
@SpringBootApplication
public class AIndexController {

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

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

}

在a项目中新建aIndexJsp.jsp文件

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript"
	src="http://www.itmayiedu.com/static/common/jquery-1.7.2.min.js?t=2017-07-27"></script>
<script type="text/javascript">
	$(document).ready(function() {
		$.ajax({
			type : "POST",
			async : false,
			url : "http://a.itmayiedu.com:8081/getBInfo",
			dataType : "json",
			success : function(data) {
				alert(data["retCode"]);
			},
			error : function() {
				alert('fail');
			}
		});

	});
</script>
</head>
<body>我是A项目,正在调用B项目
</body>
</html>

在hosts文件最下面加上如下代码:

127.0.0.1 a.itmayiedu.com
127.0.0.1 b.itmayiedu.com

启动两个项目,访问如下地址:a.itmayiedu.com:8080/aIndexJsp,这时候就会可以打开f12可以看到浏览器控制台已经报错了,调用getBInfo调用状态码200,但是没有返回值,这就是跨域问题导致的。

 

解决方案:

1、设置响应头允许跨域

这种一般都在小项目里面使用,大项目不会使用这种方式

在BIndexController里面进行修改

// 该接口提供给A项目进行ajax调用
	@RequestMapping("/getBInfo")
	public Map<String, Object> getBInfo(HttpServletResponse response) {
		// 告诉客户端(浏览器 )允许跨域访问 *表示所有域名都是可以 在公司中正常的代码应该放入在过滤器中
		response.setHeader("Access-Control-Allow-Origin", "*");
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("retCode", "200");
		result.put("retMsg", "登陆成功");
		return result;
	}

 

2、使用jsonp方式

原理:使用script发送get请求,将一个参数传过去,然后回调的时候在带回来进行解析.

将aIndexJsp的ajax请求参数进行修改:

<script type="text/javascript">
	$(document).ready(function() {
		$.ajax({
			type : "POST",
			async : false,
			url : "http://a.itmayiedu.com:8081/getBInfo",
			dataType : "jsonp",
                        jsonp : "jsonpCallback",
			success : function(data) {
				alert(data["retCode"]);
			},
			error : function() {
				alert('fail');
			}
		});

	});
</script>

BIndexController进行修改:

     //使用jsonp 解决跨域问题
     @RequestMapping("/getBInfo")
     public void getBInfo(HttpServletResponse response, String jsonpCallback) throws IOException {
         JSONObject result = new JSONObject();
         result.put("retCode", "200");
         result.put("retMsg", "登陆成功");
         PrintWriter writer = response.getWriter();
         writer.println(jsonpCallback + "(" + result.toJSONString() + ")");
         writer.close();
     }

 

3、使用httpclient内部转发

优点:安全,因此真实接口调用地址
缺点:两次请求效率低下,代码重复

实现步骤,
1.ajax请求地址还是请求本项目的地址
2.在本项目中我们接受该请求
3.在后端我们使用httpclient进行转发
4.转发之后我们在将获取到请求通过response返回到前端页面

AIndexController.java类中增加接口:

// 使用HttpClient进行方法B接口
@RequestMapping("/forWardB")
@ResponseBody
public JSONObject forWardB() {
    JSONObject result = HttpClientUtils.httpGet("http://b.itmayiedu.com:8081/getBInfo");
    return result;
}

在ajax中修改请求地址:

<script type="text/javascript">
	$(document).ready(function() {
		$.ajax({
			type : "POST",
			async : false,
			url : "http://a.itmayiedu.com:8080/forWardB",
			dataType : "json",
			success : function(data) {
				alert(data["retCode"]);
			},
			error : function() {
				alert('fail');
			}
		});

	});
</script>

4、使用nginx搭建API接口网关

nginx.conf文件配置

server {
        listen       80;
        ### 拦截域名地址
        server_name  api.itmayiedu.com;

        ### 拦截以/a开头的请求
        location /a {
            ### 指定上游服务器负载均衡服务器
            proxy_pass http://a.itmayiedu.com:8080;
            index  index.html index.htm;
        }

        location /b {
            ### 指定上游服务器负载均衡服务器
            proxy_pass http://b.itmayiedu.com:8081;
            index  index.html index.htm;
        }

    }

ajax访问地址修改:

<script type="text/javascript">
	$(document).ready(function() {
		$.ajax({
			type : "POST",
			async : false,
			url : "http://api.itmayiedu.com/b/getBInfo",
			dataType : "json",
			success : function(data) {
				alert(data["retCode"]);
			},
			error : function() {
				alert('fail');
			}
		});

	});
</script>

5、使用Zuul搭建API接口网关

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值