32

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

 1 year ago
source link: https://www.wencst.com/archives/1635
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

后端域名为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信息

修改上面的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('服务器发生错误!');
    }
});

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

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生效。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK