一、常规的后台三种解决方案
1. 全局化的配置:
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 跨域支持
* @param corsRegistry
*/
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("*") //浏览器允许所有的域访问 / 注意 * 不能满足带有cookie的访问,Origin 必须是全匹配
.allowCredentials(true) // 允许带cookie访问
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("session","Content-Type","Accept")//浏览器允许带有Content-Type,Accept,session头的请求访问
.maxAge(3600);
}
}
2. 拦截器实现
import com.cjsc.summary.exception.CommonException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/** 添加跨域支持 */
String origin = request.getHeader("Origin");
if (StringUtils.hasText(origin)) { //跨域支持
response.addHeader("Access-Control-Allow-Origin", origin);
}
//允许带有cookie访问
response.addHeader("Access-Control-Allow-Credentials", "true");
//告诉浏览器允许跨域访问的方法
response.addHeader("Access-Control-Allow-Methods", "*");
//告诉浏览器允许带有Content-Type,header1,header2头的请求访问
response.addHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,token,session");
//设置支持所有的自定义请求头
String headers = request.getHeader("Access-Control-Request-Headers");
if (StringUtils.hasText(headers)){
response.addHeader("Access-Control-Allow-Headers", headers);
}
//告诉浏览器缓存OPTIONS预检请求1小时,避免非简单请求每次发送预检请求,提升性能
response.addHeader("Access-Control-Max-Age", "3600");
return super.preHandle(request, response, handler);
}
}
然后讲拦截去添加进去:
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
CrossInterceptor crossInterceptor;
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(crossInterceptor).addPathPatterns("/**");
}
}
3. 使用注解接口定制化
@PostMapping("/bless/list")
@CrossOrigin //跨域注解,
public R findPage(@RequestBody QueryParam01Dto queryParam01Dto,@RequestAttribute("filter_user_id") Integer filterUserId) {
}
这个接口也可以定制化的配置,属性源码如下:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/** @deprecated */
@Deprecated
String[] DEFAULT_ORIGINS = new String[]{"*"};
/** @deprecated */
@Deprecated
String[] DEFAULT_ALLOWED_HEADERS = new String[]{"*"};
/** @deprecated */
@Deprecated
boolean DEFAULT_ALLOW_CREDENTIALS = true;
/** @deprecated */
@Deprecated
long DEFAULT_MAX_AGE = 1800L;
@AliasFor("origins")
String[] value() default {};
@AliasFor("value")
String[] origins() default {};
String[] allowedHeaders() default {};
String[] exposedHeaders() default {};
RequestMethod[] methods() default {};
String allowCredentials() default "";
long maxAge() default -1L;
}
二、实际问题看一把
错误1 :Access to XMLHttpRequest at 'http://127.0.0.1:8080/bless/list' from origin 'http://localhost:9999' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
解决办法:
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//遇到OPTION请求,就方过,直接返回
if (request.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS.name())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
// ......
return super.preHandle(request, response, handler);
}
}
错误2 : Access to XMLHttpRequest at 'http://127.0.0.1:8080/bless/list' from origin 'http://localhost:9999' 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.
解决办法:
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String origin = request.getHeader("Origin");
if (StringUtils.hasText(origin)) { //跨域支持
response.addHeader("Access-Control-Allow-Origin", origin);
}
//设置支持所有的自定义请求头
String headers = request.getHeader("Access-Control-Request-Headers");
if (StringUtils.hasText(headers)){
response.addHeader("Access-Control-Allow-Headers", headers);
}
//遇到OPTION请求,就方过,直接返回
if (request.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS.name())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
// ......
return super.preHandle(request, response, handler);
}
}
其实遇到OPTION就放过,这种做法并不好。最后我的做法是,单独写一个过滤器,过滤所有请求,解决的问题:
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @描述: 支持跨域拦截器
*/
@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/** 添加跨域支持 */
String origin = request.getHeader("Origin");
if (StringUtils.hasText(origin)) { //跨域支持
response.addHeader("Access-Control-Allow-Origin", origin);
}
//允许带有cookie访问
response.addHeader("Access-Control-Allow-Credentials", "true");
//告诉浏览器允许跨域访问的方法
response.addHeader("Access-Control-Allow-Methods", "*");
//告诉浏览器允许带有Content-Type,header1,header2头的请求访问
response.addHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,token,session");
//设置支持所有的自定义请求头
String headers = request.getHeader("Access-Control-Request-Headers");
if (StringUtils.hasText(headers)){
response.addHeader("Access-Control-Allow-Headers", headers);
}
//告诉浏览器缓存OPTIONS预检请求1小时,避免非简单请求每次发送预检请求,提升性能
response.addHeader("Access-Control-Max-Age", "3600");
return super.preHandle(request, response, handler);
}
}
添加拦截器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;
/**
* @作者:潘恩赐
* @QQ:3466142001
* @描述:
* @创建时间:9:43 2019/12/18
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
SessionInterceptor sessionInterceptor;
@Autowired
CrossInterceptor crossInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//特别注意,这里是两个*,一个*是会出问题的。本人就被这一个*折腾了很久。
//一个*代表/下面的一层,两个*才代表/下的所有,包括儿子的儿子。
registry.addInterceptor(crossInterceptor).addPathPatterns("/**");
registry.addInterceptor(sessionInterceptor).addPathPatterns("/bless/*");
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/15982.html