1、处理个别controller,在controller上使用@CrossOrigin注解即可
@RestController
@RequestMapping("/api")
public class SysController {
@CrossOrigin
@GetMapping("/systime")
public ApiResult sysTime() {
try {
List<SysTimeVO> sysTimeVOList = sysService.querySysTime();
return new ApiResult()
.setSuccess(true)
......
2、全局配置,配置WebMvcConfigurer
@Configuration
public class WebConfig implements WebMvcConfigurer {
// 设置允许跨域请求
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
// .allowedOrigins("http://yyy.com", "http://xxx.com") //
// 允许跨域的域名
.allowedOriginPatterns("*") // 允许所有域
.allowedMethods("*") // 允许任何方法(post、get等)
.allowedHeaders("*") // 允许任何请求头
.allowCredentials(true) // 允许证书、cookie
.exposedHeaders(HttpHeaders.SET_COOKIE)
.maxAge(3600L); // maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
}
};
}
}
3、测试
浏览器打开百度,F12调试模式,在console中粘贴如下js代码回车:
var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/api/systime');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
var xhr = e.target;
console.log(xhr.responseText);
}
不出现跨域错误即可。
4、配置有自定义拦截器时,在拦截器中获取session校验登录操作时,在拦截器preHandle方法一开始加入:
public class SessionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
return true;
}
Object obj = request.getSession().getAttribute("customer");
.......
CROS复杂请求时会首先发送一个OPTIONS请求做嗅探,来测试服务器是否支持本次请求,请求成功后才会发送真实的请求;而OPTIONS请求不会携带任何数据,导致这个请求不符合我们拦截器的校验规则被拦截了,直接返回了状态码,响应头中也没携带解决跨域需要的头部信息,进而出现了跨域问题,所以在拦截器中添加options请求处理,遇到options请求全部放行。
前端jquery ajax跨域访问:
$.ajax({
type: "get",
url: "http://xxxx.com/apiUser/currentUser",
data: "",
dataType: "json",
xhrFields:{
withCredentials:true
}
});
jquery ajax跨域访问是简单请求,不会做嗅探操作,所以加入withCredentials:true 跨域请求即可,拦截器中的针对options请求的处理针对axios等的嗅探操作。
5、拦截器返回false会引起跨域问题,解决方法是在返回false前添加如下代码:
......
PrintWriter writer = null;
try {
writer = response.getWriter();
response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
response.addHeader("Access-Control-Max-Age", "3600");
writer.print(json);
} catch (IOException e) {
} finally {
if (writer != null) writer.close();
}
}
return false;
......