最近新学习了Java EE开发框架springboot,我在使用springboot前后台分离开发的过程中遇到了跨域求问题。在网上寻找答案的过程中发现网上的解决方案大多比较零散,我在这里整理一个解决方案,但未必是最好的方案。
要在项目中解决跨域访问,需要解决三个问题:
- 服务器需要接受不同域的浏览器的请求
- 浏览器允许读取不同域的服务器的响应数据
- 保证浏览器每次访问的session是一致的
第一个问题,服务器接受不同域的浏览器的请求,这是后台开发人员需要解决的问题。具体的解决方案有几种,我这里只总结了在springboot中使用cors协议的解决方案。其实即使是springboot中cors协议解决方案也分几种不同的解决方法,下面有一种的代码,就是生成一个org.springframework.web.servlet.config.annotation.WebMvcConfigurer接口的实例对象,并且将它纳入到spring容器中。这是一个全局的方法,比较方便,当然可以为局部请求设置允许跨域访问,这里不介绍。
示例代码:
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class CreateBean { @Bean public WebMvcConfigurer corsConfigurer(){ WebMvcConfigurer configurer = new WebMvcConfigurer(){ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://127.0.0.1:8020") .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS") .allowCredentials(true).maxAge(3600); } }; return configurer; } }
代码中的registry.addMapping("/**")表示所有的请求路径都可以跨域访问。allowedOrigins("http://xxx.com:xx")代表接收的请求的原服务器地址,这个方法的参数是可变参数,可以设置多个源服务器,如果允许所有,可以使用“*”代替(但是不推荐这么写)。
解决第一个问题,那么服务器这关就通过了。但是B/S架构的web应用除了服务器,还有浏览器。在浏览器中有一个同源访问策略(火狐和谷歌都有,不知道其他的浏览器有没有),这里策略有可能禁止读取跨域访问的响应数据。其实在springboot中解决这个问题还是很简单的,只需要设置allowedOrigins()为具体的服务器地址,也就是不使用“*”代替,然后设置allowCredentials(true)就可以了
第三个问题,解决session问题。在跨域请求中,每次请求传递给服务器的sessionid是不同的,这就造成了在服务器每次都给浏览器创建一个session,所以服务器不能获取session中存放的数据,为了解决这个问题,使用jQuery的解决访问时在options参数中添加字段xhrFields:{withCredentials:true}:
$.ajax({ method:"post", url:basePath+"user/login", data:{ username:login.username, password:login.password, validateCode:login.validatecode }, xhrFields:{ withCredentials:true }, success:function(res){ console.log(res) alert(res.message) }, error:function(error){ alert(error) console.log(error) } })