一、为什么会出现跨域问题

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

总结,发生跨域必须同时满足3个条件:

1.发起请求和接收请求的协议,主机或者端口号不同,比如发起请求所在路径是http://localhost:8080,接收请求所在路径是http://localhost:8081,端口号不同,出现跨域问题

2.通过浏览器发起的请求,比如postman发起的请求就不会出现跨域问题

3.发起的请求类型是xhr(XMLHttpRequest)类型,比如json和document,javascript请求就不会出现跨域问题

为什么在浏览器地址栏输入同样的请求不会出现跨域请求报错,但是通过js等前端页面Ajax请求会出现跨域请求报错?

因为 跨域是需要有“主语”的,也就是说,是“来自某一源的代码”访问“另一源的资源”,而在地址栏中输入的请求,其主语是用户,是“用户”在访问资源,而不是“某个本地域”在访问资源。

二、什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

当前页面url 被请求页面url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 同源(协议、域名、端口号相同)
http://www.test.com/ https://www.test.com/index.html 跨域 协议不同(http/https)
http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口号不同(8080/7001)

三,本地模拟跨域请求

随便找个外网,F12后数据一下脚本 回车执行

$.ajax({
    url: "http://192.168.247.129:10000/edu/user/getUser",
    type: "get",
    contentType: "application/json",
    dataType: "json",
    success: function(data){
        if(data.msg="success"){
            alert("已提交成功");
        }else{
            alert("提交失败");
        }
    },
    error: function(data){
        alert("提交失败");
    }
});

四、解决跨域问题

首先思考解决跨域问题思路:

1.浏览器做限制:disable-web-security,禁止浏览器做跨域请求限制,这个不现实,不可能让所有客户端浏览器都做这种限制

2.JSONP:类似于把xhr请求包装成script资源来进行请求,前端dataType 改为 "jsonp" ,后端也要相应做出协议修改,不建议使用,很多时候不符合使用场景

3.接收方(服务端):

(1) 注入Filter配置跨域

package com.study.domainserver.config;import com.study.domainserver.filter.AccessFilter;
import com.study.domainserver.intercepter.AccessIntercepter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class WebConfig extends WebMvcConfigurationSupport {/***  ***********谈谈Filter和Intercepter的区别************  Web应用请求执行顺序:Filter=>Servlet=>Intercepter=>Controller*  1.Filter是Servlet容器(Tomcat)支持的,只能放在Java ee项目中;Intercepter是Spring容器支持的,既可以放在Java ee也可以放在Java se项目中*  2.Filter比Intercepter先执行*  3.Filter通过dochain放行,Interceptor通过prehandler放行。*  4.Filter只在方法前后执行,Interceptor粒度更细,可以深入到方法前后,异常抛出前后*  5.Interceptor可以获取IOC容器中的各个bean,而Filter就不行,这点很重要,在Interceptor里注入一个service,可以调用业务逻辑*//*** 设置允许跨域方法一:添加过滤器Filter** @return*/@Beanpublic FilterRegistrationBean registFilter() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(new AccessFilter());return filterRegistrationBean;}}
package com.study.domainserver.filter;import org.apache.commons.lang3.StringUtils;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class AccessFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;//允许跨域请求地址(*表示全部,但是无法满足带cookie请求,因为cookie只能在当前域请求)String requestOrigin = request.getHeader("origin");response.setHeader("Access-Control-Allow-Origin", requestOrigin);//允许接收cookie和发送cookieresponse.setHeader("Access-Control-Allow-Credentials", "true");//允许请求的方法response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");//允许请求头(Content-Type:请求数据/媒体类型 x-requested-with:判断请求是异步还是同步 自定义header 比如 token)String requestHeaders = request.getHeader("Access-Control-Request-Headers");response.setHeader("Access-Control-Allow-Headers", requestHeaders);//response.setHeader("Access-Control-Allow-Headers", "Content-Type,x-requested-with");//浏览器缓存请求头信息,1800秒内,只会有1次请求,不会出现"OPTIONS"预请求,节约资源//response.setHeader("Access-Control-Max-Age", "1800");filterChain.doFilter(request, response);}
}

(2) 注入Intercepter配置跨域

package com.study.domainserver.config;import com.study.domainserver.filter.AccessFilter;
import com.study.domainserver.intercepter.AccessIntercepter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;@Configuration
public class WebConfig extends WebMvcConfigurationSupport {/***  ***********谈谈Filter和Intercepter的区别************  Web应用请求执行顺序:Filter=>Servlet=>Intercepter=>Controller*  1.Filter是Servlet容器(Tomcat)支持的,只能放在Java ee项目中;Intercepter是Spring容器支持的,既可以放在Java ee也可以放在Java se项目中*  2.Filter比Intercepter先执行*  3.Filter通过dochain放行,Interceptor通过prehandler放行。*  4.Filter只在方法前后执行,Interceptor粒度更细,可以深入到方法前后,异常抛出前后*  5.Interceptor可以获取IOC容器中的各个bean,而Filter就不行,这点很重要,在Interceptor里注入一个service,可以调用业务逻辑*//*** 设置允许跨域方法二:添加拦截器Intercepter** @param registry*/@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AccessIntercepter()).addPathPatterns("/**");super.addInterceptors(registry);}}
package com.study.domainserver.intercepter;import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class AccessIntercepter implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//允许跨域请求地址(*表示全部,但是无法满足带cookie请求,因为cookie只能在当前域请求)//允许跨域请求地址(*表示全部,但是无法满足带cookie请求,因为cookie只能在当前域请求)String requestOrigin = request.getHeader("origin");response.setHeader("Access-Control-Allow-Origin", requestOrigin);//允许接收cookie和发送cookieresponse.setHeader("Access-Control-Allow-Credentials", "true");//允许请求的方法response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");//允许请求头(Content-Type:请求数据/媒体类型 x-requested-with:判断请求是异步还是同步 自定义header 比如 token)String requestHeaders = request.getHeader("Access-Control-Request-Headers");response.setHeader("Access-Control-Allow-Headers", requestHeaders);//response.setHeader("Access-Control-Allow-Headers", "Content-Type,x-requested-with");//浏览器缓存请求头信息,1800秒内,只会有1次请求,不会出现"OPTIONS"预请求,节约资源response.setHeader("Access-Control-Max-Age", "1800");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

(3)Controller类上加@CrossOrigin注解

package com.study.domainserver.controller;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
@CrossOrigin
public class TestController {@GetMapping("msg")public Test testMsg() throws Exception {Test test = new Test();test.setId(1);test.setName("mike");System.out.println("/test/msg。。。。。。");return test;}
}

(4) Nginx配置服务端入口配置


#Nginx用户及组:用户 组。window下不指定
#user  nobody;#工作进程:数目。根据硬件调整,通常等于CPU数量或者2倍于CPU。
worker_processes  1;#错误日志:存放路径。
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid(进程标识符):存放路径
pid       /usr/local/nginx/logs/nginx.pid;#一个进程能打开的文件描述符最大值,理论上该值因该是最多能打开的文件数除以进程数。
#但是由于nginx负载并不是完全均衡的,所以这个值最好等于最多能打开的文件数。
#LINUX系统可以执行 sysctl -a | grep fs.file 可以看到linux文件描述符。
worker_rlimit_nofile 65535;events {#使用epoll的I/O 模型。linux建议epoll,FreeBSD建议采用kqueue,window下不指定。use epoll;#单个进程最大连接数(最大连接数=连接数*进程数)worker_connections  1024;
}http {#设定mime类型,类型由mime.type文件定义include       mime.types;default_type  application/octet-stream;#服务器名字的hash表大小server_names_hash_bucket_size 128;#tcp_nodelay off 会增加通信的延时,但是会提高带宽利用率。在高延时、数据量大的通信场景中应该会有不错的效果#tcp_nodelay on,会增加小包的数量,但是可以提高响应速度。在及时性高的通信场景中应该会有不错的效果tcp_nodelay on;#长连接超时时间,单位是秒keepalive_timeout  65;server {listen 80;server_name 192.168.247.130;location /{root html;index index.html index.htm;#解决跨域问题#允许跨域请求地址(*表示全部,但是无法满足带cookie请求,因为cookie只能在当前域请求)add_header Access-Control-Allow-Origin $http_origin;#允许接收cookie和发送cookieadd_header Access-Control-Allow-Credentials 'true';#允许请求的方法add_header Access-Control-Allow-Methods 'GET,POST,DELETE,PUT,OPTIONS';#允许请求头(Content-Type:请求数据/媒体类型 x-requested-with:判断请求是异步还是同步 自定义header 比如 token)add_header Access-Control-Allow-Headers $http_access_control_request_headers;#浏览器缓存请求头信息,1800秒内,只会有1次请求,不会出现"OPTIONS"预请求,节约资源#add_header Access-Control-Max-Age '1800';if ($request_method = 'OPTIONS') {return 204;}proxy_pass http://192.168.247.130:8081;}  }
}

关于web项目跨域问题详解相关推荐

  1. proxytable代理不生效_proxyTable代理跨域使用详解

    这次给大家带来proxyTable代理跨域使用详解,proxyTable代理跨域使用的注意事项有哪些,下面就是实战案例,一起来看一下. 什么是代理跨域 浏览器之间有同源策略,出于安全考虑不同域之间不允 ...

  2. jQuery中getJSON跨域原理详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...

  3. web开发的跨域问题详解

    2019独角兽企业重金招聘Python工程师标准>>> 本文由云+社区发表 做过 web 开发的同学,应该都遇到过跨域的问题,当我们从一个域名向另一个域名发送 Ajax 请求的时候, ...

  4. vue-admin-template解决跨域问题详解

    vue-admin-template入门详解(后端springboot+sprngsecurity+jwt+redis) 自&如 2020-05-10 23:25:09 1232 收藏 10 ...

  5. jsonp 跨域原理详解

    转载至:http://zha-zi.iteye.com/blog/1975116 JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制 ...

  6. 深和jsonp【转】 jsonpk跨域问题详解

    取不到数据! 上周客户新买了服务器,原本在旧的服务器上放着客户的Web主页信息和一个后台程序(asp.net),在客户的主页中有一个动态显示最新消息的处理,这个处理就是通过ajax异步从那个后台程序中 ...

  7. Ajax 跨域请求详解

    问题描述: 实际开发中,我们经常会看到这样的错误提示: XMLHttpRequest cannot load http://-- No 'Access-Control-Allow-Origin' he ...

  8. vue如何配置服务器端跨域_客户端(vue框架)与服务器(koa框架)通信及服务器跨域配置详解...

    本篇博客主要说明: 前后端框架(本例中是vue和koa)如何发送请求?获取响应? 以及跨域问题如何解决? vue部分: import App from './App.vue' import Axios ...

  9. AJAX请求和跨域请求详解(原生JS、Jquery)

    一.概述 AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术. AJAX = 异步 JavaScript 和 XML,是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数 ...

最新文章

  1. Oracle 12c 新特性之 temp undo
  2. BZOJ 1412 [ZJOI2009]狼和羊的故事(最小割)
  3. 仿ios便签软件_手机便签软件误删怎么恢复?
  4. 深度学习(七)—— GAN
  5. 72. 编辑距离(JavaScript)
  6. 月薪一万在石家庄能过什么样的生活?
  7. 福建省计算机类考生,福建一档多投对考生是有利的,“滑档”的锅甩给计算机吗?...
  8. [WCF编程]10.操作:请求/应答操作
  9. 群晖 VMM虚拟机安装openwrt软路由做单臂旁路由
  10. ELK日志分析系统理论加实操演练!!
  11. 2021腾讯校招前端一面
  12. 安徽农业大学计算机考研分数线,安徽农业大学2019年考研复试分数线已公布
  13. One Piece Introduction
  14. java取0到999整数_Java中输入一个0到999的整数 怎么弄? 谢谢了、
  15. 反病毒工具-OllyDBG 和 UPX
  16. Apple Sign in with Apple(苹果授权登录PHP)
  17. 记一次简单学习MarkDown语法
  18. 【色彩管理】锐印添加ICC曲线教程
  19. top SRM526.5
  20. VSTO | C#快速开发电子签章插件

热门文章

  1. python3 django html 中文乱码_解决django后台管理界面添加中文内容乱码问题
  2. allergo 导出光辉配置_请教Allegro导出光绘文件的层要选择哪些层?
  3. mysql 代替分号_php – mysql FIND_IN_SET()用分号代替逗号
  4. win7 64位运行不了服务器,G6-e标准包可以装在win7 64位系统上吗?现在提示不能登陆到服务器...
  5. java svn配置环境变量,Android环境变量配置和安装SVN
  6. 设计个人介绍界面(用SWING控件),并添加各种组件练习
  7. 如果战斗机飞行员弹出,自动驾驶仪会接管飞机安全降落么?
  8. 第16课 “远程 Git文档库” 的基础操作
  9. Mongo 常用的server命令
  10. 禅道程序员的10条原则--转载--为了不忘