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

一、什么是跨域问题

        是两个项目之间使用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依赖


		org.springframework.boot
		spring-boot-starter-parent
		2.0.0.RELEASE
	
	
		
		
			org.projectlombok
			lombok
		

		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter-tomcat
		
		
		
			org.apache.tomcat.embed
			tomcat-embed-jasper
		

		
		
			org.springframework.boot
			spring-boot-starter-log4j
			1.3.8.RELEASE
		
		
		
			org.springframework.boot
			spring-boot-starter-aop
		
		
			org.apache.httpcomponents
			httpclient
		
		
		
			com.alibaba
			fastjson
			1.2.47
		
	

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 getBInfo() {
		Map result = new HashMap();
		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"%>




Insert title here



我是A项目,正在调用B项目

在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 getBInfo(HttpServletResponse response) {
		// 告诉客户端(浏览器 )允许跨域访问 *表示所有域名都是可以 在公司中正常的代码应该放入在过滤器中
		response.setHeader("Access-Control-Allow-Origin", "*");
		Map result = new HashMap();
		result.put("retCode", "200");
		result.put("retMsg", "登陆成功");
		return result;
	}

 

2、使用jsonp方式

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

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

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中修改请求地址:

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

五种网站跨域问题解决方案_第1张图片

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访问地址修改:

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

 

 

你可能感兴趣的:(跨域)