跨域后台解决方案。

导读:本篇文章讲解 跨域后台解决方案。,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、常规的后台三种解决方案

1. 全局化的配置:


import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    /**
     *  跨域支持
     * @param corsRegistry
     */
    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {
        corsRegistry.addMapping("/**")
                .allowedOrigins("*")    //浏览器允许所有的域访问 / 注意 * 不能满足带有cookie的访问,Origin 必须是全匹配
                .allowCredentials(true) // 允许带cookie访问
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("session","Content-Type","Accept")//浏览器允许带有Content-Type,Accept,session头的请求访问
                .maxAge(3600);
    }
}

2. 拦截器实现


import com.cjsc.summary.exception.CommonException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /**  添加跨域支持 */

        String origin = request.getHeader("Origin");
        if (StringUtils.hasText(origin)) { //跨域支持
            response.addHeader("Access-Control-Allow-Origin", origin);
        }
        //允许带有cookie访问
        response.addHeader("Access-Control-Allow-Credentials", "true");
        //告诉浏览器允许跨域访问的方法
        response.addHeader("Access-Control-Allow-Methods", "*");
        //告诉浏览器允许带有Content-Type,header1,header2头的请求访问
        response.addHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,token,session");
        //设置支持所有的自定义请求头
        String headers = request.getHeader("Access-Control-Request-Headers");
        if (StringUtils.hasText(headers)){
            response.addHeader("Access-Control-Allow-Headers", headers);
        }
        //告诉浏览器缓存OPTIONS预检请求1小时,避免非简单请求每次发送预检请求,提升性能
        response.addHeader("Access-Control-Max-Age", "3600");

        return super.preHandle(request, response, handler);
    }
}

然后讲拦截去添加进去:


import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;


@Configuration
public class WebConfig implements WebMvcConfigurer {

	
    @Autowired
    CrossInterceptor crossInterceptor;

	//添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	registry.addInterceptor(crossInterceptor).addPathPatterns("/**");
    }
}

3. 使用注解接口定制化

 	@PostMapping("/bless/list")
    @CrossOrigin   //跨域注解,
    public R findPage(@RequestBody QueryParam01Dto queryParam01Dto,@RequestAttribute("filter_user_id") Integer filterUserId) {
    
    }

这个接口也可以定制化的配置,属性源码如下:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
    /** @deprecated */
    @Deprecated
    String[] DEFAULT_ORIGINS = new String[]{"*"};
    /** @deprecated */
    @Deprecated
    String[] DEFAULT_ALLOWED_HEADERS = new String[]{"*"};
    /** @deprecated */
    @Deprecated
    boolean DEFAULT_ALLOW_CREDENTIALS = true;
    /** @deprecated */
    @Deprecated
    long DEFAULT_MAX_AGE = 1800L;

    @AliasFor("origins")
    String[] value() default {};

    @AliasFor("value")
    String[] origins() default {};

    String[] allowedHeaders() default {};

    String[] exposedHeaders() default {};

    RequestMethod[] methods() default {};

    String allowCredentials() default "";

    long maxAge() default -1L;
}

二、实际问题看一把

错误1Access to XMLHttpRequest at 'http://127.0.0.1:8080/bless/list' from origin 'http://localhost:9999' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

解决办法:


import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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


@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      	//遇到OPTION请求,就方过,直接返回
        if (request.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }      
     	// ......
        return super.preHandle(request, response, handler);
    }
}

错误2Access to XMLHttpRequest at 'http://127.0.0.1:8080/bless/list' from origin 'http://localhost:9999' 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.

解决办法:


import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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


@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      
      	String origin = request.getHeader("Origin");
        if (StringUtils.hasText(origin)) { //跨域支持
            response.addHeader("Access-Control-Allow-Origin", origin);
        }
		//设置支持所有的自定义请求头
        String headers = request.getHeader("Access-Control-Request-Headers");
        if (StringUtils.hasText(headers)){
            response.addHeader("Access-Control-Allow-Headers", headers);
        }

        //遇到OPTION请求,就方过,直接返回
        if (request.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }      
     	// ......
        return super.preHandle(request, response, handler);
    }
}

其实遇到OPTION就放过,这种做法并不好。最后我的做法是,单独写一个过滤器,过滤所有请求,解决的问题:


import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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

/**
 * @描述: 支持跨域拦截器
 */

@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /**  添加跨域支持 */

        String origin = request.getHeader("Origin");
        if (StringUtils.hasText(origin)) { //跨域支持
            response.addHeader("Access-Control-Allow-Origin", origin);
        }
        //允许带有cookie访问
        response.addHeader("Access-Control-Allow-Credentials", "true");
        //告诉浏览器允许跨域访问的方法
        response.addHeader("Access-Control-Allow-Methods", "*");
        //告诉浏览器允许带有Content-Type,header1,header2头的请求访问
        response.addHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,token,session");
        //设置支持所有的自定义请求头
        String headers = request.getHeader("Access-Control-Request-Headers");
        if (StringUtils.hasText(headers)){
            response.addHeader("Access-Control-Allow-Headers", headers);
        }
        //告诉浏览器缓存OPTIONS预检请求1小时,避免非简单请求每次发送预检请求,提升性能
        response.addHeader("Access-Control-Max-Age", "3600");

        return super.preHandle(request, response, handler);
    }
}

添加拦截器:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

/**
 * @作者:潘恩赐
 * @QQ:3466142001
 * @描述:
 * @创建时间:9:43 2019/12/18
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    SessionInterceptor sessionInterceptor;

    @Autowired
    CrossInterceptor crossInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	 //特别注意,这里是两个*,一个*是会出问题的。本人就被这一个*折腾了很久。
    	 //一个*代表/下面的一层,两个*才代表/下的所有,包括儿子的儿子。
        registry.addInterceptor(crossInterceptor).addPathPatterns("/**");  
        registry.addInterceptor(sessionInterceptor).addPathPatterns("/bless/*");
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/15982.html

(0)
小半的头像小半

相关推荐

极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!