SpringBoot跨域请求处理方法 总结

在项目开发过程中不可避免的就是跨域请求,以下下是跨域请求处理的几种方法总结

1. 直接采用SpringBoot的注解@CrossOrigin

   Controller层在需要跨域的类或者方法上加上该注解即可。

2. 处理跨域请求的Configuration继承WebMvcConfigurerAdapter或者实现WebMvcConfigurer接口

例如:CrossOriginConfig.java

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * AJAX请求跨域
 * @author Mr.W
 * @time 2018-08-13
 */
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
    static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS)
                .maxAge(3600);
    }
}

3. 采用过滤器的方式Filter

@Component
public class CORSFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    HttpServletResponse res = (HttpServletResponse) response;
    res.addHeader("Access-Control-Allow-Credentials", "true");
    res.addHeader("Access-Control-Allow-Origin", "*");
    res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
    res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
    if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
        response.getWriter().println("ok");
        return;
    }
    chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

}

4. 引入maven依赖:

<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-core</artifactId>
    <version>RELEASE</version>
</dependency>
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;


@Configuration
public class RouteConfiguration {
    //这里为支持的请求头,如果有自定义的header字段请自己添加(不知道为什么不能使用*)
    private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client";
    private static final String ALLOWED_METHODS = "*";
    private static final String ALLOWED_ORIGIN = "*";
    private static final String ALLOWED_Expose = "*";
    private static final String MAX_AGE = "18000L";

    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (CorsUtils.isCorsRequest(request)) {
                ServerHttpResponse response = ctx.getResponse();
                HttpHeaders headers = response.getHeaders();
                headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
                headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
                headers.add("Access-Control-Max-Age", MAX_AGE);
                headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
                headers.add("Access-Control-Expose-Headers", ALLOWED_Expose);
                headers.add("Access-Control-Allow-Credentials", "true");
                if (request.getMethod() == HttpMethod.OPTIONS) {
                    response.setStatusCode(HttpStatus.OK);
                    return Mono.empty();
                }
            }
            return chain.filter(ctx);
        };
    }
}

5. 前后分离的跨域问题其他解决方案

Nginx服务器反向代理

通过反向代理服务器监听同端口,同域名的访问,不同路径映射到不同的地址,比如,在nginx服务器中,监听同一个域名和端口,不同路径转发到客户端和服务器,把不同端口和域名的限制通过反向代理,来解决跨域的问题。

server {
        listen       80;
        server_name  abc.com;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;

        location /client { #访问客户端路径
            proxy_pass http://localhost:81;
            proxy_redirect default;
        }
        location /apis { #访问服务器路径
            rewrite  ^/apis/(.*)$ /$1 break;
            proxy_pass   http://localhost:82;
       }
}

直接在Nginx中进行配置

location / {
   add_header Access-Control-Allow-Origin *;
   add_header Access-Control-Allow-Headers X-Requested-With;
   add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

   if ($request_method = 'OPTIONS') {
     return 204;
   }
}

6 还有一种使用 jsonp 的调用方式,不过好像太古老了

JSON的核心是:动态添加script标签来调用服务器提供的js脚本。JQuery ajax本质上是通过script标签实现跨域请求,而非真正的ajax请求。整个过程可简单描述为:客户端跨域请求数据responseData,然后使用客户端js函数handleResponse(responseData)对数据进行处理。具体实现思路为:客户端封装一个脚本请求如
<script src="https://www.jsonp_request.com/request_method?callback=handleResponse&param1=valu1...">
其中handleResponse为本地JS函数;然后,服务器端获取callback的回调函数名即handleResponse后,将处理结果responseData,包装成javascript函数调用的形式,即字符串“handleResponse({responseData的json数据})”传回客户端;最后,客户端使用eval(返回字符串);执行返回结果。

JQuery封装JSONP请求:对于经常使用jQuery的开发者来说,肯定注意到jQuery封装的$.ajax中有一个dataType属性,如果将该属性设置成dataType:“jsonp”,就能实现JSONP跨域了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jQuery实现JSONP</title>
</head>
<body>
    <div id="mydiv">
        <button id="btn">点击</button>
    </div>
</body>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script type="text/javascript">
    $(function(){
        $("#btn").click(function(){
 
            $.ajax({
                async : true,
                url : "https://api.douban.com/v2/book/search",
                type : "GET", //如果是跨域请求或将crossDomain设置为true,则type只能是GET
                dataType : "jsonp", // 返回的数据类型,设置为JSONP方式
                jsonp : 'callback', //指定一个查询参数名称来覆盖默认的 jsonp 回调参数名 callback
                jsonpCallback: 'handleResponse', //设置回调函数名,默认jquery自定义
                data : {
                    q : "javascript", 
                    count : 1
                }, 
                success: function(response, status, xhr){ //返回数据,即response.data
                    console.log('状态为:' + status + ',状态是:' + xhr.statusText);
                    console.log(response);
                }
            });
        });
    });
</script>

其实,在JQuery的JSONP实现中,首先将你在success中定义的函数封装成jsonpCallback定义的函数,然后再封装一个脚本请求如
<script src="https://api.douban.com/v2/book/search?callback=handleResponse&q=javascript&count=1">

JSONP请求,缺点是仅支持GET请求,必须完全信任提供服务的第三方,优点是支持老式浏览器,兼容性较好。CORS比JSONP更强大,支持所有类型的HTTP请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值