欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Spring Boot 2.0.2+Ajax解决跨域请求的问题

程序员文章站 2024-02-15 20:47:52
问题描述 后端域名为a.abc.com,前端域名为b.abc.com。浏览器在访问时,会出现跨域访问。浏览器对于javascript的同源策略的限制。 http请求...

问题描述

后端域名为a.abc.com,前端域名为b.abc.com。浏览器在访问时,会出现跨域访问。浏览器对于javascript的同源策略的限制。

http请求时,请求本身会返回200,但是返回结果不会走success,并且会在浏览器console中提示:

已拦截跨源请求:同源策略禁止读取位于 https://www.baidu.com/ 的远程资源。(原因:cors 头缺少 ‘access-control-allow-origin')。

解决方案

1.jsonp

2.引用a站的js

3.nginx做a站的反向代理

4.后端服务放开跨域请求

其中,以最后两种见常。

详细方案

本文主要描述第四种解决方案:后端服务放开跨域请求。

spring boot中放开跨域请求很简单。

1.增加一个configuration类

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.cors.corsconfiguration;
import org.springframework.web.cors.urlbasedcorsconfigurationsource;
import org.springframework.web.filter.corsfilter;

/**
 * 跨域访问配置
 * @author wencst
 * @creation 2017年8月18日
 */
@configuration
public class customcorsconfiguration {
 private corsconfiguration buildconfig() {
 corsconfiguration corsconfiguration = new corsconfiguration();
 corsconfiguration.addallowedorigin("*");
 corsconfiguration.addallowedheader("*");
 corsconfiguration.addallowedmethod("*");
 return corsconfiguration;
 }
 @bean
 public corsfilter corsfilter() {
 urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource();
 source.registercorsconfiguration("/**", buildconfig());
 return new corsfilter(source);
 }
}

增加此类以后,非同源http访问可以正常进行了,但是会不会有什么问题呢?

对于大部分网站依然需要使用cookie作为前后端传输数据的媒介,然而默认非同源请求是不携带cookie信息的。

2.服务端允许跨域携带cookie信息

在spring boot2.0.2中,允许跨域设置比较简单,只需增加一个configuration类即可。

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.cors.corsconfiguration;
import org.springframework.web.cors.urlbasedcorsconfigurationsource;
import org.springframework.web.filter.corsfilter;

/**
 * 跨域访问配置
 * @author wencst
 * @creation 2017年8月18日
 */
@configuration
public class customcorsconfiguration {
 private corsconfiguration buildconfig() {
 corsconfiguration corsconfiguration = new corsconfiguration();
 corsconfiguration.addallowedorigin("*");
 corsconfiguration.addallowedheader("*");
 corsconfiguration.addallowedmethod("*");
 corsconfiguration.addexposedheader("content-type");
 corsconfiguration.addexposedheader( "x-requested-with");
 corsconfiguration.addexposedheader("accept");
 corsconfiguration.addexposedheader("origin");
 corsconfiguration.addexposedheader( "access-control-request-method");
 corsconfiguration.addexposedheader("access-control-request-headers");
 corsconfiguration.setallowcredentials(true);
 return corsconfiguration;
 }
 @bean
 public corsfilter corsfilter() {
 urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource();
 source.registercorsconfiguration("/**", buildconfig());
 return new corsfilter(source);
 }
}

增加信息后,在前端依然需要调整ajax请求,才能在非同源请求中携带cookie信息。

3.前端调整

$.ajax({
 url: 'http://beta.roboming.com/api.php?s=/public/adminlogin.html',
 type: 'post',
 async:true,
 xhrfields:{
  withcredentials:true
 },
 data: {
  username:username,
  password:pwd
 },
 success: function(respon){
  console.log(respon);
  var res=eval(respon);
 },
 error: function(){
  alert('服务器发生错误!');
 }
});

此时,当前端向后端服务做跨域请求时,增加

xhrfields:{
  withcredentials:true
},

就会带上cookie信息了,同理会带上token/sessionid等等内容。

测试方法

spring boot中增加一个controller

@controller
public class logincontroller {
 @requestmapping(value = "setstring")
 @responsebody
 public string setstring(httpservletrequest request, httpservletresponse response,@requestparam string value) {
 request.getsession().setattribute("username", value);
 return "ok";
 }
 @requestmapping(value = "getstring")
 @responsebody
 public string getstring(httpservletrequest request, httpservletresponse response) {
 string username = (string)request.getsession().getattribute("username");
 return username;
 }
}

增加一个index.html,来访问跨域访问。

<html>
<head>
<meta charset="utf-8">
<title>跨域请求</title>
<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<button onclick="set()">set</button>
<br><br>
<button onclick="get()">get</button>
<script>
function set(){
 $.ajax({
 url:'http://wencst.vicp.net/setstring?value=10',
 xhrfields:{
  withcredentials:true
 },
 success:function(result){
 alert(result);
 }
 });
}
function get(){
 $.ajax({
 url:'http://wencst.vicp.net/getstring',
 xhrfields:{
  withcredentials:true
 },
 success:function(result){
 alert(result);
 }
 });
}
</script>
</body>
</html>

html文件可以单独本地访问即可出现效果,并不一定要形成服务访问。

当服务端不允许跨域访问时,html文件访问均报错,并调用失败。

当服务端允许跨域访问时,html请求访问成功。

当服务端开启cookie传递,并在html文件中增加 xhrfields参数时,session生效

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。