xuziwen127
xuziwen127
采纳率61.1%
2019-01-17 22:46 阅读 10.5k
已采纳

spring boot设置了Access-Control-Allow-Origin还是有跨域问题

5

最近使用spring cloud框架进行前后端分离开发,因为我们是通过网关去访问后台接口,ip
、端口都相同,所以没有出现过跨域问题,但是前端的同事把项目用webstrom打开以后(端口和ip就成了webstrom分配的)就有了跨域问题无法请求到后台,浏览器报"CORS 头缺少 'Access-Control-Allow-Origin'",但是我们已经在网关里设置了Access-Control-Allow-Origin为*,代码如下:

@Service
public class AuthFilter extends ZuulFilter {
    /**
     * 日志对象
     */
    private static final Logger logger = LoggerFactory.getLogger(AuthFilter.class);
    @Autowired
    private FilterConfig filterConfig;
    /**
     * redis缓存
     */
    @Autowired
    private RedisService redisService;
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();
        //解决浏览器跨域问题
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
//        response.addHeader("Access-Control-Allow-Credentials", "true");
//        response.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
//        response.addHeader("Access-Control-Max-Age", "3600");
//        response.addHeader("Vary", "Origin");
        response.addHeader("Access-Control-Allow-Headers", "token,accesstoken,Content-type");
        //请求接口URL时登录token有效性校验
        return null;
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

}

对此我在本地随便写了个小项目还原了当时的情景,我把代码以及报错贴出来麻烦各位看一下哪里有不对的;
前端代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script src="js/jquery-1.9.1.min.js"></script>
    </head>
    <script>
        function t1(){
            $.ajax({
                url:'http://localhost:9001/xzw/say',
                type:'post',
                contentType : 'application/json;charset=utf-8', 
                dataType:'json',
                data : JSON.stringify({
                    batch_id : 'ncveirugheasolvgil'
                }),
                success : function(data){
                    alert('成功跨域');
                    alert(data);
                },
                error : function(){
                    alert('error');
                }
            })
        }
    </script>
    <body>
        <input type="button" value="测试跨域是否能获取数据" onclick="t1()"/>
    </body>
</html>

后台代码:

@RestController
@RequestMapping("/xzw")
public class PageDemoController {
    @RequestMapping("/say")
    public String say(HttpServletRequest request,HttpServletResponse response,@RequestParam(value="batch_id")String batch_id){
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.addHeader("Access-Control-Allow-Headers", "*");
        System.out.println("batch_id="+batch_id);


        return "hello world";
    }
}

浏览器报错

已拦截跨源请求:同源策略禁止读取位于 http://localhost:9001/xzw/say 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。[详细了解]

已拦截跨源请求:同源策略禁止读取位于 http://localhost:9001/xzw/say 的远程资源。(原因:CORS 请求未能成功)。[详细了解]

我们项目里的拦截器原本除了设置Access-Control-Allow-Origin还有验证token的代码,前端如果先进行登陆然后在ajax请求的时候把token拿到放在header里就不会有跨域问题,我把token验证的代码去掉了就出现了跨域问题,但是我看验证token的逻辑判断对跨域没有什么特殊的处理,一下为拦截器原代码:

public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();
        //解决浏览器跨域问题
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
//        response.addHeader("Access-Control-Allow-Credentials", "true");
//        response.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
//        response.addHeader("Access-Control-Max-Age", "3600");
//        response.addHeader("Vary", "Origin");
        response.addHeader("Access-Control-Allow-Headers", "token,accesstoken,Content-type");
        //请求接口URL时登录token有效性校验
        Object token = request.getHeader("token");
        if(token==null||token.equals("")) {
            token = null;
        }
        boolean flag = false;//请求路径是否在过滤范围标识
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            ctx.setSendZuulResponse(false);
            return null;
        }
        String ignores = filterConfig.getIgnores();
        if(!StringUtilHelper.isEmpty(ignores)) {
            String[] ignores_arr = ignores.split(",");
            for(String ignore:ignores_arr) {
                if(request.getRequestURI().toString().contains(ignore)) {
                    //无需token校验
                    flag = true;
                    break;
                }
            }
        }
        logger.info("网关日志:method={}, uri={},result={},token={}",request.getMethod(), request.getRequestURI(), (true==flag?"无需token校验":"需要token校验"),token);
        if(!flag) {
            //需要校验token有效性
            if(token==null) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
                ctx.setResponseBody("token为空,未认证用户");
                return null;
            } else {
                //redis校验
                if(redisService.check(token.toString())!=ServiceConstants.STATE_1) {
                    ctx.setSendZuulResponse(false);
                    ctx.setResponseStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
                    ctx.setResponseBody("token超时,请重新登录");
                    return null;
                }
            }
        }
        return null;
    }
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

8条回答 默认 最新

  • 已采纳
    ctqshwsz //Q 2019-01-18 17:52

    在 你的AuthFilter 里面把shouldFilter() 替换成这个

    @Override
        public boolean shouldFilter() {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
                    HttpServletResponse response = ctx.getResponse();
            if("OPTIONS".equals(request.getMethod())){
                //过滤该请求,不往下级服务去转发请求,到此结束  
                ctx.setSendZuulResponse(false); 
                ctx.setResponseStatusCode(200);  
                ctx.getResponse().setContentType("text/html;charset=UTF-8");
                ctx.setResponseBody("true");
                                response.setHeader("Access-Control-Allow-Origin", "*");
                                response.setHeader("Access-Control-Allow-Credentials", "true");
                                response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
                                response.setHeader("Access-Control-Max-Age", "3600");
                                response.addHeader("Access-Control-Allow-Headers", "token,accesstoken,Content-type");
                return false;
            }
            return true;
        }
    
    
    点赞 评论 复制链接分享
  • devmiao devmiao 2019-01-17 23:53
  • zhongsan123 才沐木 2019-01-18 08:23

    是不是web.xml没有设置跨域访问的配置?例如

     <!--跨域访问配置-->
        <filter>
           <filter-name>CORS</filter-name>
           <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
           <init-param>
            <param-name>cors.allowOrigin</param-name>
               <param-value>*</param-value>
           </init-param>
           <init-param>
            <param-name>cors.supportedMethods</param-name>
               <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
           </init-param>
           <init-param>
            <param-name>cors.supportedHeaders</param-name>
               <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
           </init-param>
           <init-param>
               <param-name>cors.exposedHeaders</param-name>
               <param-value>Set-Cookie</param-value>
           </init-param>
           <init-param>
               <param-name>cors.supportsCredentials</param-name>
               <param-value>true</param-value>
           </init-param>
       </filter>
    
       <filter-mapping>
           <filter-name>CORS</filter-name>
           <url-pattern>*.do</url-pattern>
       </filter-mapping>
    
    点赞 评论 复制链接分享
  • wkwk12345 勤劳的代码搬运工 2019-01-18 09:36

    跨域请求ajax的 把dataType的json换成jsonp。

    点赞 评论 复制链接分享
  • qq_37129624 ghq-yes 2019-01-18 09:41

    请求的Origin属性设置有影响吗

    点赞 评论 复制链接分享
  • weixin_43072335 weixin_43072335 2019-01-18 10:24

    解决跨域问题添加配置文件

    /**

    • @Description: 解决跨域问题
      /
      @Configuration
      public class CorsConfig {
      private CorsConfiguration buildConfig() {
      CorsConfiguration corsConfiguration = new CorsConfiguration();
      corsConfiguration.addAllowedOrigin("
      ");
      corsConfiguration.addAllowedHeader("*");
      corsConfiguration.addAllowedMethod("*");
      return corsConfiguration;
      }

      @Bean
      public CorsFilter corsFilter() {
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      source.registerCorsConfiguration("/**", buildConfig());
      return new CorsFilter(source);
      }

    点赞 评论 复制链接分享
  • tavatimsa tavatimsa 2019-01-18 14:02
    @Configuration
    public class MvcConfig extends WebMvcConfigurationSupport {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            //设置允许跨域的路径
            registry.addMapping("/**")
                    //设置允许跨域请求的域名
                    .allowedOrigins("*")
                    //是否允许证书 不再默认开启
                    .allowCredentials(true)
                    //设置允许的方法
                    .allowedMethods("*")
                    //跨域允许时间
                    .maxAge(3600);
        }
    
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("swagger-ui.html")
                    .addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
    }
    

    试试这个吧。我们都是用这个就行了。

    点赞 评论 复制链接分享
  • xuziwen127 xuziwen127 2019-08-06 18:22

    大家说的方法都是对的,我当时是请求头里没有带Access-Control-Allow-Headers里设置好的属性所以产生了无法跨域的情况,我随便算一个采纳了

    点赞 评论 复制链接分享

相关推荐