五中常见的跨域问题以及处理方案

什么是网站跨域

跨域原因产生:在当前域名请求网站中,默认不允许通过ajax请求发送其他域名,即浏览器安全策略问题。

 

网站跨域报错案例

 

jquery-1.7.2.min.js?t=2020-09-07:4 Failed to load http://b.mytest.com:8081/ajaxB: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.mytest.com:8080' is therefore not allowed access.

 

五种网站跨域解决方案

 

  1. 使用jsonp解决网站跨域 
  2. 使用HttpClient内部转发
  3. 使用设置响应头允许跨域
  4. 基于Nginx搭建企业级API接口网关
  5. 使用Zuul搭建微服务API接口网关

 

跨域项目环境搭建

 

使用JSONP解决网站跨域

 

前端代码

<script type="text/javascript"

      src="http://www.mytest.com/static/common/jquery-1.7.2.min.js?t=2020-09-07"></script>

<script type="text/javascript">

      $(document).ready(function() {

           $.ajax({

                 type : "GET",

                 async : false,

                 url : "http://b.mytest.com:8081/ajaxB",

                 dataType : "jsonp",

                 jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数

                 success : function(data) {

                      alert(data["errorCode"]);

                 },

                 error : function() {

                      alert('fail');

                 }

           });

 

      });

</script>

 

后端代码

      @RequestMapping(value = "/ajaxB", method = RequestMethod.GET)

      public void ajaxB(HttpServletResponse response, String jsonpCallback) throws IOException {

           JSONObject root = new JSONObject();

           root.put("errorCode", "200");

           root.put("errorMsg", "登陆成功");

           response.setHeader("Content-type", "text/html;charset=UTF-8");

           PrintWriter writer = response.getWriter();

           writer.print(jsonpCallback + "(" + root.toString() + ")");

           writer.close();

      }

 

缺点:不支持post请求,代码书写比较复杂

 

使用设置响应头允许跨域

 

前端代码

<script type="text/javascript"

      src="http://www.mytest.com/static/common/jquery-1.7.2.min.js?t=2020-09-07"></script>

<script type="text/javascript">

      $(document).ready(function() {

           $.ajax({

                 type : "GET",

                 async : false,

                 url : "http://b.mytest.com:8081/ajaxB",

                 dataType : "json",

                 success : function(data) {

                      alert(data["errorCode"]);

                 },

                 error : function() {

                      alert('fail');

                 }

           });

 

      });

</script>

 

后端代码

@RequestMapping("/ajaxB")

public Map<String, Object> ajaxB(HttpServletResponse response) {

      response.setHeader("Access-Control-Allow-Origin", "*");

      Map<String, Object> result = new HashMap<String, Object>();

      result.put("errorCode", "200");

      result.put("errorMsg", "登陆成功");

      return result;

}

 

 

 

 

 

 

response.setHeader("Access-Control-Allow-Origin", "*"); 设置响应头允许跨域

如果在实际项目中,该代码建议放在过滤器中。

 

 

使用HttpClient进行内部转发

前端代码

<script type="text/javascript"

      src="http://www.mytest.com/static/common/jquery-1.7.2.min.js?t=2020-09-07"></script>

<script type="text/javascript">

      $(document).ready(function() {

           $.ajax({

                 type : "POST",

                 async : false,

                 url : "http://a.mytest.com:8080/forwardB",

                 dataType : "json",

                 success : function(data) {

                      alert(data["errorCode"]);

                 },

                 error : function() {

                      alert('fail');

                 }

           });

 

      });

</script>

 

 

后端代码

 

A项目进行转发到B项目

 

@RequestMapping("/forwardB")

      @ResponseBody

      public JSONObject forwardB() {

           JSONObject result = HttpClientUtils.httpGet("http://b.mytest.com:8081/ajaxB");

           System.out.println("result:" + result);

           return result;

      }

 

B项目代码

 

@RequestMapping("/ajaxB")

public Map<String, Object> ajaxB(HttpServletResponse response) {

           response.setHeader("Access-Control-Allow-Origin", "*");

           Map<String, Object> result = new HashMap<String, Object>();

           result.put("errorCode", "200");

           result.put("errorMsg", "登陆成功");

           return result;

      }

 

缺点:多次请求!

 

搭建企业级API接口网关

使用Nginx搭建API接口网关

 Nginx相关配置

   server {

        listen       80;

        server_name  www.mytest.com;

 

                   ###A项目

        location /a {

            proxy_pass   http://a.mytest.com:8080/;

            index  index.html index.htm;

        }

                   ###B项目

                    location /b {

            proxy_pass   http://b.mytest.com:8081/;

            index  index.html index.htm;

        }

    }

 

 前端代码

<script type="text/javascript"

      src="http://code.jquery.com/jquery-1.8.0.min.js"></script>

<script type="text/javascript">

      $(document).ready(function() {

           $.ajax({

                 type : "POST",

                 async : false,

                 url : "http://www.mytest.com/b/ajaxB",

                 dataType : "json",

                 success : function(data) {

                      alert(data["errorCode"]);

                 },

                 error : function() {

                      alert('fail');

                 }

           });

 

      });

</script>

 

后端代码

     @RequestMapping("/ajaxB")

     public Map<String, Object> ajaxB(HttpServletResponse response) {

          response.setHeader("Access-Control-Allow-Origin", "*");

         Map<String, Object> result = new HashMap<String, Object>();

         result.put("errorCode", "200");

         result.put("errorMsg", "登陆成功");

         return result;

     }

 

 

SpringCloud搭建API接口网关

 

使用SpringCloud Zuul搭建API接口网关

Maven初始化依赖参数

<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

server:

  port: 8080

spring:

  mvc:

    view:

      prefix: /WEB-INF/jsp/

      suffix: .jsp

 

HttpClientUtils工具类

public class HttpClientUtils {

      private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录

 

      private static RequestConfig requestConfig = null;

 

      static {

           // 设置请求和传输超时时间

           requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();

      }

 

      /**

       * post请求传输json参数

       *

       * @param url

       *            url地址

       * @param json

       *            参数

       * @return

       */

      public static JSONObject httpPost(String url, JSONObject jsonParam) {

           // post请求返回结果

           CloseableHttpClient httpClient = HttpClients.createDefault();

           JSONObject jsonResult = null;

           HttpPost httpPost = new HttpPost(url);

           // 设置请求和传输超时时间

           httpPost.setConfig(requestConfig);

           try {

                 if (null != jsonParam) {

                      // 解决中文乱码问题

                      StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");

                      entity.setContentEncoding("UTF-8");

                      entity.setContentType("application/json");

                      httpPost.setEntity(entity);

                 }

                 CloseableHttpResponse result = httpClient.execute(httpPost);

                 // 请求发送成功,并得到响应

                 if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                      String str = "";

                      try {

                            // 读取服务器返回过来的json字符串数据

                            str = EntityUtils.toString(result.getEntity(), "utf-8");

                            // json字符串转换成json对象

                            jsonResult = JSONObject.parseObject(str);

                      } catch (Exception e) {

                            logger.error("post请求提交失败:" + url, e);

                      }

                 }

           } catch (IOException e) {

                 logger.error("post请求提交失败:" + url, e);

            } finally {

                 httpPost.releaseConnection();

           }

           return jsonResult;

      }

 

      /**

       * post请求传输String参数 例如:name=Jack&sex=1&type=2

       * Content-type:application/x-www-form-urlencoded

       *

       * @param url

       *            url地址

       * @param strParam

       *            参数

       * @return

       */

      public static JSONObject httpPost(String url, String strParam) {

           // post请求返回结果

           CloseableHttpClient httpClient = HttpClients.createDefault();

           JSONObject jsonResult = null;

           HttpPost httpPost = new HttpPost(url);

           httpPost.setConfig(requestConfig);

           try {

                 if (null != strParam) {

                      // 解决中文乱码问题

                      StringEntity entity = new StringEntity(strParam, "utf-8");

                      entity.setContentEncoding("UTF-8");

                      entity.setContentType("application/x-www-form-urlencoded");

                      httpPost.setEntity(entity);

                 }

                 CloseableHttpResponse result = httpClient.execute(httpPost);

                 // 请求发送成功,并得到响应

                 if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                      String str = "";

                      try {

                            // 读取服务器返回过来的json字符串数据

                            str = EntityUtils.toString(result.getEntity(), "utf-8");

                            // json字符串转换成json对象

                            jsonResult = JSONObject.parseObject(str);

                      } catch (Exception e) {

                            logger.error("post请求提交失败:" + url, e);

                      }

                 }

           } catch (IOException e) {

                 logger.error("post请求提交失败:" + url, e);

           } finally {

                 httpPost.releaseConnection();

           }

           return jsonResult;

      }

 

      /**

       * 发送get请求

       *

       * @param url

       *            路径

       * @return

       */

      public static JSONObject httpGet(String url) {

           // get请求返回结果

           JSONObject jsonResult = null;

           CloseableHttpClient client = HttpClients.createDefault();

           // 发送get请求

           HttpGet request = new HttpGet(url);

           request.setConfig(requestConfig);

           try {

                 CloseableHttpResponse response = client.execute(request);

 

                 // 请求发送成功,并得到响应

                 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                      // 读取服务器返回过来的json字符串数据

                      HttpEntity entity = response.getEntity();

                      String strResult = EntityUtils.toString(entity, "utf-8");

                      // json字符串转换成json对象

                      jsonResult = JSONObject.parseObject(strResult);

                 } else {

                      logger.error("get请求提交失败:" + url);

                 }

           } catch (IOException e) {

                 logger.error("get请求提交失败:" + url, e);

           } finally {

                 request.releaseConnection();

           }

           return jsonResult;

      }

 

}

 

  1. 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://code.jquery.com/jquery-1.8.0.min.js"></script>

<script type="text/javascript">

      $(document).ready(function() {

           $.ajax({

                 type : "POST",

                 async : false,

                 url : "http://www.mytest.com/b/ajaxB",

                 dataType : "json",

                 success : function(data) {

                      alert(data["errorCode"]);

                 },

                 error : function() {

                      alert('fail');

                 }

           });

 

      });

</script>

</head>

<body>显示 ....

</body>

</html>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot中处理跨域问题可以通过配置跨域请求的过滤器来实现。具体实现步骤如下: 1. 创建一个过滤器类,实现javax.servlet.Filter接口。 2. 在过滤器类中添加@Order注解,指定过滤器的执行顺序。 3. 在过滤器类中重写doFilter方法,在方法中添加跨域请求处理代码。 4. 在Spring Boot的配置类中添加@Bean注解,将过滤器类注册到Spring容器中。 以下是一个示例代码: ```java @Component @Order(Ordered.HIGHEST_PRECEDENCE) public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; HttpServletRequest request = (HttpServletRequest) req; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Content-Length, X-Requested-With"); if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } } @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { return new CorsFilter(); } } ``` 在上述代码中,过滤器类CorsFilter实现了javax.servlet.Filter接口,并使用@Order注解指定了过滤器的执行顺序。在doFilter方法中,设置了跨域请求的响应头,如果是OPTIONS请求则直接返回200状态码,否则执行下一个过滤器。在配置类CorsConfig中,将CorsFilter注册到Spring容器中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书耳朵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值