• 跨域问题实战 2


    跨域问题实战 2


    背景

    由于整个项目提供出去的API都不是跨域的只是个别是需要跨域的,所以再上一次跨域问题实战中,自己是直接再controller层其中需要提供出去跨域的方法里设置了HttpServletResponse.setHeader("Access-Control-Allow-Origin","*")。而且上次提供出去的只是一次简单的get请求,而不是复杂请求。但是呢,这次的需求是记录用户行为日志的一次跨域请求,也就是说是一次post请求。其中就涉及到http请求的Content-Type中application/json和application/x-www-form-urlencoded。还涉及到springMVC中的@RequestBody这个注解。其中这些问题,就下一篇博客再详细记录。因为涉及到post中的application/json所以就涉及到跨域的复杂请求。

    问题重现

    由于ajax默认的contentType是application/x-www-form-urlencoded。所以自己对这次请求设置的是application/json
    代码如下

    
        var data = {
            "userId" : 20142100122,
            "userOperationStep" : 2,
            "appPlatform": "android",
            "app" : 0,
            "videoId":123123
        };
    
        $.ajax({
            url : 'http://xxxxxx/xxxxc/xxx/vippromotion',
            type : 'POST',
            dateType : 'json',
            contentType : 'application/json',
            data:JSON.stringify(data),
            success : function(msg){
                console.log(msg);
            }
        })
    

    由于自己只想让该接口可以被进行跨域操作所以自己再controller层是单独设置的跨域请求的
    部分代码如下

     public Json vippromotion(@RequestBody VipPromotionLog vipPromotionLog, HttpServletResponse response){
            response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600"); 
            response.setHeader("Allow","POST");
            response.setHeader("Access-Control-Allow-Credentials ", "true");
            .......
    
    }
    

    看清楚自己这里设置了Access-Control-Allow-Headers允许了复杂请求,但是却出现如下错误
    如图一

    图一
    ![](https://i.loli.net/2018/12/11/5c0f517d1f9c9.png)

    但是Ajax请求却没有失败。如图二

    图二
    ![](https://i.loli.net/2018/12/11/5c0f519a36b73.png)

    排查

    由于自己再该接口中设置了允许复杂请求,但是却根本没有进来,所以并不是跨域代码错误。这里就得说一下什么是复杂请求了。复杂请求是会进行两次请求得,一次是预请求,一次是真正得请求。 从上面得例子可以看出,自己只是对真正得请求进行跨域处理,但是却没有对预请求进行跨域处理。所以导致跨域失败。

    解决

    设置过滤器,对每次进行进行跨域处理代码如下

      @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("doFilter--------------start");
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Allow","POST");
            response.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
            response.setHeader("Access-Control-Allow-Credentials ", "true");
            System.out.println("doFilter--------------end");
            filterChain.doFilter(servletRequest, res);
        }
    

    web.xml中得我就不贴了。
    运行项目发起请求,请求处理如下图三:

    图三
    ![](https://i.loli.net/2018/12/11/5c0f51a8ba932.png)

    看到了没有两次请求。

    然后我们再发起一次请求来看一下,结果如下图四

    图四

    只有一次请求,这是因为设置了 response.setHeader("Access-Control-Max-Age", "3600");6分钟内不用再发起预请求。

    防止

    如果是一个单独给外界提供接口得项目得话,我建议设置一个跨域处理得过滤器。如果只是一个项目中一两个接口是提供给别人得,别人是跨域操作得话,尽量是简单请求。就是用ajax中默认得参数application/x-www-form-urlencoded

  • 相关阅读:
    four day (linux基础学习1)
    three day(网络基础)
    two day(操作系统)
    Oldboy One day(计算机基础)
    mybatis调用存储过程
    调用jiathis分享接口
    汉字转换拼音工具类
    Ajax前后台交互 返回普通格式和JSON格式
    Bootstrap与EasyUI入门
    MD5,sha1加密工具类
  • 原文地址:https://www.cnblogs.com/Krloypower/p/9277053.html
Copyright © 2020-2023  润新知