• springboot中的跨域问题


    springboot中的跨域问题,如果不注意的话,容易造成错误,本次springboot版本为2.13  前端错误信息:

    Access to XMLHttpRequest at 'http://localhost:8080/user/loginOn' from origin 'http://localhost:8082' 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.

    第一种:是在每个Controller里,加上注解:@CrossOrigin

    import javax.validation.Valid;
    @CrossOrigin
    @RestController
    @RequestMapping("/user")
    public class UserController{

    也可以在方法上加上,比如这样,这样针对具体的方法

      @CrossOrigin
        @ApiOperation(value = "用户登录",notes = "")
        @PostMapping("/loginOn")
        public ResponseMessage loginOn(@RequestBody @Valid UserReq userReq){

    每一个Controller这样写也是很麻烦。

    第二种:是实现WebMvcConfigurer接口,在接口中进行跨域支持

    以前可以继承WebMvcConfigurerAdapter,springboot2.x版本已经将其@Deprecated

    我们直接实现接口:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        /**
         * 跨域支持
         * @param registry
         */
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowCredentials(true)
                    .allowedMethods("GET", "POST", "DELETE", "PUT")
                    .maxAge(3600 * 24);
        }

    但使用这种方法,我今天遇到一个坑,我准备在拦截器里面对用户的请求进行拦截

    @Component
    public class RequestInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
           Object loginUser = request.getSession().getAttribute("token");
            if(loginUser == null){
            //自定义的异常类,这里抛出异常,交给全局异常捕捉类处理 throw new ServiceException("没有权限,请先登录!"); }else{ return true; }
    } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }

    全局异常捕捉类:

    @RestControllerAdvice
    public class GlobleExceptionHandler {
        @ExceptionHandler(value = ServiceException.class)
        public ResponseMessage caughtException(ServiceException e){
    
            return new ResponseMessage(e.getMsg());
        }
    }
    ResponseMessage 是自定义的统一的响应信息类:
    @Data
    public class ResponseMessage {
        private Integer Code;
        private String msg;
        private Integer count;
        private Object data;
    
        public ResponseMessage(Object data) {
            this.data = data;
        }
    
        public ResponseMessage(String msg) {
            this.msg = msg;
        }
    
        public ResponseMessage(Integer code, String msg) {
            Code = code;
            this.msg = msg;
        }
    
        public ResponseMessage(Integer code, String msg, Integer count) {
            Code = code;
            this.msg = msg;
            this.count = count;
        }
    
        public ResponseMessage(Integer code, String msg, Integer count, Object data) {
            Code = code;
            this.msg = msg;
            this.count = count;
            this.data = data;
        }
    
        public static  ResponseMessage success(String msg){
            return new ResponseMessage(200,msg);
        }
    
        public static ResponseMessage fail(Integer code,String msg){
            return new ResponseMessage(code,msg);
        }
    }
    ResponseMessage

    通过这样的处理发现,前端一直报跨域异常问题,这时候有了第三种方法

    第三种:使用CorsFilter过滤器:

    写一个MyCorsConfig 配置类

    @Configuration
    public class MyCorsConfig {
    
        @Bean
        public CorsFilter corsFilter() {
    
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin("*");
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            corsConfiguration.setAllowCredentials(true);
            corsConfiguration.setMaxAge(3600L);
    
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", corsConfiguration);
            FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
            //设置过滤器的顺序
            bean.setOrder(0);
            return new CorsFilter(source);
        }
    }

    最终解决本次demo的跨域问题。

    第四种:采用springcloud  gateway实现跨域:

    采用上述配置时,发现没有起作用:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.reactive.CorsWebFilter;
    import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
    
    @Configuration
    public class MyCorsConfig {
    
        @Bean
        public CorsWebFilter corsWebFilter(){
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    
            CorsConfiguration corsConfiguration = new CorsConfiguration();
    
            //1、配置跨域
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            corsConfiguration.addAllowedOrigin("*");
            corsConfiguration.setAllowCredentials(true);
    
            source.registerCorsConfiguration("/**",corsConfiguration);
            return new CorsWebFilter(source);
        }
    }

    也可以采用yml的配置形式:

    spring:
      cloud:
        gateway:
          # 跨域
          globalcors:
            corsConfigurations:
              '[/**]':
                allowedHeaders: "*"
                allowedOrigins: "*"
                allowedMethods:
                - GET
                  POST
                  DELETE
                  PUT
                  OPTION

    官方配置参考:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#cors-configuration

    可能出现报错:

    The 'Access-Control-Allow-Origin' header contains multiple values 'http://lo“,but onl one is allowed

    原因是gateway里设置了跨域,在调用的微服务里面也设置了跨域,设置了多个跨域,去掉微服务里面的即可。

  • 相关阅读:
    在vue中格式化表格中的时间为指定格式
    vlookup匹配数据
    .net core 导出文件到浏览器
    SQL语句 不足位数补0
    获取两个月份间的所有月份列表
    WIN10安装MYSQL教程
    在IDEA中使用@Slf4j报错,找不到log报错
    mybatis plus 动态表名 SQL 解析【我】
    Linux下搭建FTP服务器的方法
    关于行结束符(CR、LF)
  • 原文地址:https://www.cnblogs.com/tdyang/p/12141816.html
Copyright © 2020-2023  润新知