跨域问题解决方案

1、什么是跨域

因为浏览器有一个同源策略(SOP),当不同的域名端口、协议的项目内去请求其他项目的接口,要把结果直接显示在浏览器页面的时候,这个时候浏览器因为同源策略SOP,这个时候会拒绝解析请求的结果同时报错405.(注意:这个时候是可以拿到请求的结果的,但是不能显示结果),这就是跨域的问题。为了解决跨域的问题,制定了一个标准,CROS(允许跨域)。

2、跨域问题的解决方案

第一:jsonp

缺点:只能使用get请求

            a项目前端代码:

<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 : "GET",

async : false,

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

dataType : "jsonp",

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

success : function(data) {

alert(data["errorCode"]);

},

error : function() {

alert('fail');

}

});

 

});

script>

b项目后端代码

@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();

}

第二:使用HTTPclient转发

a项目的页面先访问a项目的转发接口,a项目的转发接口再真正请求b项目的请求接口,请求的接口返回数据,这样做就间接是a项目的页面访问拿到b项目的请求接口的返回结果给浏览器。

缺点:太麻烦,这样每次请求都需要写转发接口,效率比较低

a项目的页面

<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:8080/forwardB",

dataType : "json",

success : function(data) {

alert(data["errorCode"]);

},

error : function() {

alert('fail');

}

});

 

});

script>

a项目的转发接口

@RequestMapping("/forwardB")

@ResponseBody

public JSONObject forwardB() {

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

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

return result;

}

b项目真正的请求接口

@RequestMapping("/ajaxB")

public Map ajaxB(HttpServletResponse response) {

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

Map result = new HashMap();

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

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

return result;

}

第三:设置请求头响应跨域,实现 webMVCAdapter接口,重写允许跨域的方法

响应头中设置 response.setHeader("Access-Control-Allow-Origin", "*"),为单个接口设置允许跨域;也可以一整个springboot项目实现webMVCAdapter接口,重写里面关于跨域的方法允许所有的接口跨域。

@RequestMapping("/ajaxB")

public Map ajaxB(HttpServletResponse response) {

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

Map result = new HashMap();

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

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

return result;

}

实现webnmvcconfigadapter接口,为整个项目所有接口允许跨域


@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
 
    /*@Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("*")
                .allowedMethods("PUT", "DELETE")
                .allowedHeaders("header1", "header2", "header3")
                .exposedHeaders("header1", "header2")
                .allowCredentials(false).maxAge(3600);
    }*/
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/public/");
    }
}

第四:使用nginx搭建网关允许跨域

使用nginx搭建网关允许跨域的原理是:把不同的项目用同一个域名进行访问,一不同的路径来区分不同的项目,在nginx中配置拦截配置,从而各个项目之间的域名、端口号都一样,这样就不会出现跨域的问题。

nginx相关配置

   server {

        listen       80;

        server_name  www.itmayiedu.com;

 

###A项目

        location /a {

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

            index  index.html index.htm;

        }

###B项目

 location /b {

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

            index  index.html index.htm;

        }

    }

a项目前端代码

<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.itmayiedu.com/b/ajaxB",

dataType : "json",

success : function(data) {

alert(data["errorCode"]);

},

error : function() {

alert('fail');

}

});

 

});

script>

b项目后端代码

@RequestMapping("/ajaxB")

public Map ajaxB(HttpServletResponse response) {

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

Map result = new HashMap();

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

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

return result;

}

第五:使用springcloud gateway网关跨域

springcloud解决跨域的问题就是利用网关的转发,统一访问网关的端口,根据访问路径由网关转发到各个不同的服务

第六:前后端分离的项目,使用node服务器转发允许跨域

前端使用vue,那么在vue项目中新建vue.config.js文件设置跨域

let proxyObj = {};
proxyObj['/ws'] = {
    ws: true,
    target: "ws://localhost:8081"
};
//拦截http请求
proxyObj['/'] = {
    ws: false, //webscoket关掉
    target: 'http://localhost:8081',  //你要把拦截到转化到哪里去
    changeOrigin: true,        //是否需要跨域
    pathRewrite: {  //是否需要重写拦截到的地址
        '^/': ''
    }
}
module.exports = {
    devServer: {  //前端服务本身的信息
        host: 'localhost',  //前端服务的域名
        port: 8080,  //前端服务的端口
        proxy: proxyObj  //前端服务的代理对象
    }
}

 文章参考:蚂蚁课堂

 

 

 

 

 

 

你可能感兴趣的:(跨域问题解决方案)