• springboot CORS 跨域请求解决三大方案,springboot CorsFilter解决跨域问题


    springboot CORS 跨域请求解决三大方案,springboot CorsFilter解决跨域问题

    springboot CORS解决 No 'Access-Control-Allow-Origin' header is present on the requested resource

    ================================

    ©Copyright 蕃薯耀 2020-11-24

    https://www.cnblogs.com/fanshuyao/

    跨域请求,一般是在页面调用ajax请求向别的应用服务发送请求,因域名不相同,导致跨域

    解决跨域请求的方式有:

    一、远程服务器支持跨域请求(CORS 跨域)

    二、使用nginx反向代理

    三、服务器端使用Http请求

    四、使用jsonp(需要应用服务器支持)

    下面以远程服务器支持跨域请求(CORS 跨域)为例:

    其中有三种方式让远程服务器支持跨域请求

    方式一、使用注解:@CrossOrigin

    1、在类上加注解,表示类下所有方法都支持跨域请求

    @CrossOrigin
    @RestController
    @RequestMapping("cross")
    public class AaaController {
    
    }

    2、在方法加注解,表示该方法运动跨域请求

    @RestController
    @RequestMapping("cross")
    public class AaaController {
    
        @CrossOrigin
        @RequestMapping("/bbb")
        public Result bbb(HttpServletRequest request, HttpServletResponse response) throws Exception {
            ……
        }
    }

    方式二、实现WebMvcConfigurer接口,重写addCorsMappings方法(官方文档全局配置跨域请求使用的是此方式)

    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    import com.test.util.JsonUtil;
    
    
    @Configuration
    public class MvcConfig implements WebMvcConfigurer {
    
        /**
         * 解决跨域请求
         * @return
         */
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
            .allowCredentials(true)
            .allowedOrigins("*")
            .allowedHeaders("*")
            .allowedMethods("*")
            .maxAge(3600);
    
            WebMvcConfigurer.super.addCorsMappings(registry);
        }
    
    
    
        /**
         * 解决@RestController返回json结果时,IE浏览器出现下载json文件的现象。
         * @return
         */
        @Bean
        public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
            MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
            
            List<MediaType> supportedMediaTypes  = new ArrayList<MediaType>();
            supportedMediaTypes.add(new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")));
            supportedMediaTypes.add(new MediaType(MediaType.TEXT_HTML, Charset.forName("UTF-8")));
            jsonConverter.setSupportedMediaTypes(supportedMediaTypes);
            
            jsonConverter.setObjectMapper(JsonUtil.getMapper());//设置使用jackson转换器
            
            return jsonConverter;
        }
        
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(jackson2HttpMessageConverter());
        }
    
        
    }

    方式三、使用CorsFilter过滤器

    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    @Configuration
    public class HttpFilterConfig {
    
        @Bean
        public FilterRegistrationBean<CorsFilter> corsFilter() {
            CorsConfiguration corsConfig = new CorsConfiguration();
            corsConfig.setAllowCredentials(true);
            corsConfig.addAllowedOrigin(CorsConfiguration.ALL);
            corsConfig.addAllowedMethod(CorsConfiguration.ALL);
            corsConfig.addAllowedHeader(CorsConfiguration.ALL);
            //默认可不设置这个暴露的头。这个为了安全问题,不能使用*。设置成*,后面会报错:throw new IllegalArgumentException("'*' is not a valid exposed header value");
            //corsConfig.addExposedHeader("");
            corsConfig.setMaxAge(3600L);
            
            UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
            configSource.registerCorsConfiguration("/**", corsConfig);
            
            FilterRegistrationBean<CorsFilter> corsBean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(configSource));
            corsBean.setName("crossOriginFilter");
            corsBean.setOrder(0);//这个顺序也有可能会有影响,尽量设置在拦截器前面
            return corsBean;
        }
        
        
    }

    前端页面调用示例:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>跨域请求</title>
    <script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
    </head>
    <body>
    
        <div>跨域请求</div>
        
    <script type="text/javascript">
    function ajax(){
        console.log("ajax()");
        $.ajax({  
            //async: false,//设置为同步,默认为异步(一般不需要)  
            url : "http://aaa.com:7010/gtkjCghj/workflow/processes",  //aaa.com域名修改host文件
            type : "post",  
            dataType : "json",
            //contentType: "application/json;charset=UTF-8",//contentType如果设置成application/json;charset=UTF-8,就会会变成复杂请求,导致发送2次请求,第一次是options请求,第二次才是真正的请求。
            data : {
                "processName" : "报批",
                "gxDocNo": "f2-202000234",
                "ssotoken":"eyJpc3N1Y2Nlc3MiOiJ0cnVlIiwiZmFpbHJlc29uIjoiIiwiYWNjb3VudCI6Inplbmd6aW0iLCJ0b2tlbiI6ImE5YzA5YTdjYWRlOTQwNjFiNzdmYzMxNjhkZDI2Mzc3In0=.Eg4DFhERDQ=="
            },
            complete : function(XMLHttpRequest, textStatus){  
                //alert("textStatus="+textStatus);  
            },  
            error : function(XMLHttpRequest, textStatus, errorThrown){  
                if("error" == textStatus){  
                    alert("服务器未响应,请稍候再试");  
                }else{  
                    alert("请求失败,textStatus="+textStatus);  
                }  
             },  
             success : function(data){  
                 if(data != null){  
                     console.log("data===" + JSON.stringify(data));
                 }else{  
                     alert("返回结果为空!");  
                 }  
             }  
        }); 
    };
    
    
    ajax();
    </script>
    
    </body>
    </html>

    注意事项: 

    需要注意的是ajax请求中的contentType

    contentType默认的值是:application/x-www-form-urlencoded,当不设置或者为默认值时,这个是简单请求,只发送1次真正的请求。
    如果contentType设置成"application/json;charset=UTF-8"会变成复杂请求,导致发送2次请求,第一次是options请求,第二次才是真正的请求。

    部分服务器,是禁止发送OPTIONS请求的,这样会导致跨域问题:

    jquery-3.4.1.min.js:2 OPTIONS http://test.com/gtkjCghj/workflow/processes 401 (Unauthorized)
    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.

    简单请求
    只要同时满足以下条件就属于简单请求
    1、请求方法是以下三种方法之一:GET、POST、HEAD
    2、Http的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type。

    Content-Type只限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/plain

    简单请求的请求头示例:
    其中:Content-Type: application/x-www-form-urlencoded; charset=UTF-8

    POST /gtkjCghj/workflow/processes HTTP/1.1
    Host: aaa.com:7010
    Connection: keep-alive
    Content-Length: 212
    Accept: application/json, text/javascript, */*; q=0.01
    Origin: http://127.0.0.1:7010
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Referer: http://127.0.0.1:7010/gtkjCghj/static/cross.html
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9

    非简单请求,发送OPTIONS的请求头:

    OPTIONS /gtkjCghj/workflow/processes HTTP/1.1
    Host: aaa.com
    Connection: keep-alive
    Access-Control-Request-Method: POST
    Origin: http://aaa.com:7010
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
    Access-Control-Request-Headers: content-type
    Accept: */*
    Referer: http://127.0.0.1:7010/gtkjCghj/static/cross.html
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9

    总结:cors跨域请求解决方案(建议采用方案1)

    1、springboot CORS 跨域请求解决三大方案,springboot CorsFilter解决跨域问题

    https://www.cnblogs.com/fanshuyao/p/14030944.html

    2、cors-filter使用,cors-filter解决跨域访问,cors-filter跨域请求

    https://www.cnblogs.com/fanshuyao/p/14036848.html

    3、org.ebaysf.web的cors-filter使用,cors-filter跨域请求

    https://www.cnblogs.com/fanshuyao/p/14042293.html

    4、java tomcat-catalina CorsFilter使用,apache tomcat-catalina CorsFilter使用

    https://www.cnblogs.com/fanshuyao/p/14042420.html

    5、springboot jsonp 跨域请求,springboot使用jsonp跨域

    https://www.cnblogs.com/fanshuyao/p/14034014.html

    ================================

    ©Copyright 蕃薯耀 2020-11-24

    https://www.cnblogs.com/fanshuyao/

  • 相关阅读:
    EF中读取随机数据的问题
    【坐在马桶上看算法】算法3:最常用的排序——快速排序
    C#递归算法
    机器学习策略(二)---误差分析、训练集与开发测试集不相配怎么办、迁移学习/多任务学习、端到端深度学习
    机器学习策略(一)---正交化、评估指标、优化指标、训练与测试集数据集大小、可避免误差
    改善深层神经网络的优化算法:mini-batch梯度下降、指数加权平均、动量梯度下降、RMSprop、Adam优化、学习率衰减
    具有单隐藏层的二分类神经网络
    神经网络前向后向传播(理论与实战)
    梯度消失与梯度爆炸---如何选择随机初始权重
    正则化输入
  • 原文地址:https://www.cnblogs.com/fanshuyao/p/14030944.html
Copyright © 2020-2023  润新知