前后端分离跨域问题

跨域问题是什么?怎么产生的?我不在这里说明,请大家百度,google去,说的很详细。

这里我要说的是,我配置了跨域针对部分请求好使,但是部分请求又不好使这个问题。

相信java开发的小伙伴,前后端分离,后端使用的代码一定都是使用spring boot搭建的。

那么spring boot搭建的项目,官方为我们提供了解决跨域的方式,比如下面这样:

    CorsConfiguration config = new CorsConfiguration();
    //允许所有域名进行跨域调用
    config.addAllowedOrigin("*");
    //允许跨越发送cookie
    config.setAllowCredentials(true);
    //放行全部原始头信息
    config.addAllowedHeader("*");
    //允许所有请求方法跨域调用
    config.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return new org.springframework.web.filter.CorsFilter(source);

看下我项目的目录结构

代码如下:

CorsFilter

package com.peng.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * CORS问题spring配置的解决方案
 */
@Configuration
public class CorsFilter {

  @Bean
  public org.springframework.web.filter.CorsFilter corsFilter1() {
    CorsConfiguration config = new CorsConfiguration();
    //允许所有域名进行跨域调用
    config.addAllowedOrigin("*");
    //允许跨越发送cookie
    config.setAllowCredentials(true);
    //放行全部原始头信息
    config.addAllowedHeader("*");
    //允许所有请求方法跨域调用
    config.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return new org.springframework.web.filter.CorsFilter(source);
  }
}

FilterConfig

package com.peng.config;

import com.peng.filter.demoFilter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 初始化过滤器
 */
@Configuration
public class FilterConfig {

  /**
   * 拦截所有请求
   * @return
   */
  @Bean
  public FilterRegistrationBean jwtFilter() {
    final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    registrationBean.setFilter(new demoFilter());
    registrationBean.addUrlPatterns("/*");
    return registrationBean;
  }

}

demoFilter

package com.peng.filter;

import org.springframework.web.filter.GenericFilterBean;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class demoFilter extends GenericFilterBean {

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;

    String authorization = request.getHeader("Authorization");

    response.setContentType("text/html;charset=UTF-8");
    response.getWriter().write("您好");
    return;

  }
}

Demo

package com.peng.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
public class Demo {

  @RequestMapping(value = "demo", method = RequestMethod.GET)
  public String getStr(HttpServletRequest request, HttpServletResponse response) {
    return "demo";
  }
}

说明下,我代码中增加了过滤器,过滤器的目的是为了获取header中的的鉴权信息进行认证,相信前后端分离的,很多采用token,放到header的Authorization。

下面我们来测试下,跨域请求的测试,不能直接在浏览器的地址栏请求,需要我们使用F12,在console模拟ajax请求,

$.ajax({
    type:"GET",
    url:"http://localhost:8080/demo",
    dataType:"JSON",
    data:{
    },
    beforeSend: function (XMLHttpRequest) {
        XMLHttpRequest.setRequestHeader("Authorization", '123123');
    },
    success:function(res){
        console.log(res.code)
    }
})

注意异常:

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.

上面这个异常就是跨域请求提示的异常。

网上很多人配置了跨域,仍然会遇到跨域的问题。但是当我们把过滤器关掉,你再试试。

是不是请求成功了。

由此我们可以推断,是因为过滤器的原因。spring boot 提供的跨域配置对过滤器无效了。

解决方案:

我这里的做法是,放弃spring boot 提供的跨域解决方案,使用

    // cors 跨域问题解决
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "*");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

这里我们修改demoFilter

package com.peng.filter;

import org.springframework.web.filter.GenericFilterBean;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class demoFilter extends GenericFilterBean {

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;

    // cors 跨域问题解决
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "*");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

    String authorization = request.getHeader("Authorization");

    response.setContentType("text/html;charset=UTF-8");
    response.getWriter().write("您好");
    return;

  }
}

注释掉CorsFilter

运行看下结果

问题解决了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值