详解Spring Boot 2.0.2+Ajax解决跨域请求的问题
问题描述
后端域名为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生效
。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读