跨域问题是什么?怎么产生的?我不在这里说明,请大家百度,google去,说的很详细。
这里我要说的是,我配置了跨域针对部分请求好使,但是部分请求又不好使这个问题。
相信java开发的小伙伴,前后端分离,后端使用的代码一定都是使用spring boot搭建的。
那么spring boot搭建的项目,官方为我们提供了解决跨域的方式,比如下面这样:
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new org.springframework.web.filter.CorsFilter(source);
看下我项目的目录结构
代码如下:
CorsFilter
package com.peng.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
/**
* CORS问题spring配置的解决方案
*/
@Configuration
public class CorsFilter {
@Bean
public org.springframework.web.filter.CorsFilter corsFilter1() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new org.springframework.web.filter.CorsFilter(source);
}
}
FilterConfig
package com.peng.config;
import com.peng.filter.demoFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 初始化过滤器
*/
@Configuration
public class FilterConfig {
/**
* 拦截所有请求
* @return
*/
@Bean
public FilterRegistrationBean jwtFilter() {
final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new demoFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
demoFilter
package com.peng.filter;
import org.springframework.web.filter.GenericFilterBean;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class demoFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String authorization = request.getHeader("Authorization");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("您好");
return;
}
}
Demo
package com.peng.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
public class Demo {
@RequestMapping(value = "demo", method = RequestMethod.GET)
public String getStr(HttpServletRequest request, HttpServletResponse response) {
return "demo";
}
}
说明下,我代码中增加了过滤器,过滤器的目的是为了获取header中的的鉴权信息进行认证,相信前后端分离的,很多采用token,放到header的Authorization。
下面我们来测试下,跨域请求的测试,不能直接在浏览器的地址栏请求,需要我们使用F12,在console模拟ajax请求,
$.ajax({
type:"GET",
url:"http://localhost:8080/demo",
dataType:"JSON",
data:{
},
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Authorization", '123123');
},
success:function(res){
console.log(res.code)
}
})
注意异常:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
上面这个异常就是跨域请求提示的异常。
网上很多人配置了跨域,仍然会遇到跨域的问题。但是当我们把过滤器关掉,你再试试。
是不是请求成功了。
由此我们可以推断,是因为过滤器的原因。spring boot 提供的跨域配置对过滤器无效了。
解决方案:
我这里的做法是,放弃spring boot 提供的跨域解决方案,使用
// cors 跨域问题解决
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
这里我们修改demoFilter
类
package com.peng.filter;
import org.springframework.web.filter.GenericFilterBean;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class demoFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// cors 跨域问题解决
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
String authorization = request.getHeader("Authorization");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("您好");
return;
}
}
注释掉CorsFilter
运行看下结果
问题解决了。