解决跨越的几种方式


跨域请求

的定义:协议 + 域名 + 端口
三者完全相同则为同域,反之有其一不同均为不同域,
当前发起请求请求指向 属于不同域时,该次请求称之为跨域请求。

  1. A应用只能访问 A 应用后台传来数据,B 应用只能访问 B 应用后台传来的数据;

  2. 如果 A 应用用 Ajax 获取数据时的 URL 地址中的协议、端口、域名其中有一个和 B 应用对应的话,则是 A 应用跨域获取 B 应用数据,是不允许的。

    同源策略

    同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

  3. 同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。

  4. 所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

    跨域的几种情况

  • 同一域名下允许通信(未指定端口协议)
  • 同一域名下不同文件夹允许通信
  • 同一域名不同端口不允许通信
  • 同一域名不同协议不允许通信
  • 域名和域名对应IP不允许通信
  • 主域名相同,子域名不同不允许通信
  • 同一域名,不同二级域名不允许通信
  • 不同域名不允许通信
当前页面 URL 被请求URL 是否跨越 原因
http://www.baidu.com http://www.baidu.com/java.html 同源(协议,域名,端口均相同)
http://www.baidu.com https://www.baidu.com/java.html 跨越 协议不同(http,https)
http://www.baidu.com http://www.google.com 跨越 主域名不同(baidu,google)
http://www.baidu.com http://zhidao.baidu.com 跨越 子域名不同(www,zhidao)
http://www.baidu.com:8080 http://www.baidu.com:90 跨越 端口不同(80,90))

1. 定义 CorsFilter (全局跨域)

在配置类中,返回一个 新的 CorsFIlter Bean ,并添加映射路径和具体的CORS配置路径。

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1. 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        config.addAllowedOrigin("*");
        //是否发送 Cookie
        config.setAllowCredentials(true);
        //放行哪些请求方式
        config.addAllowedMethod("*");
        //放行哪些原始请求头部信息
        config.addAllowedHeader("*");
        //暴露哪些头部信息
        config.addExposedHeader("*");
        //2. 添加映射路径
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**",config);
        //3. 返回新的CorsFilter
        return new CorsFilter(corsConfigurationSource);
    }
}

2. 重写 WebMvcConfigurer (全局跨域)

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //放行哪些原始域
                .allowedOrigins("*")
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

3. 使用自定义 Filter (全局跨域)

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

4. 使用注解 (局部跨域)

在 crontaller 类或者方法上使用注解 @CrossOrigin 表示该类的所有方法允许跨域。

# 在类上面设置
@RestController
@CrossOrigin(origins = "*")
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "hello world";
    }
}



# 在方法上面设置
@RequestMapping("/hello")
@CrossOrigin(origins = "*")
//@CrossOrigin(value = "http://localhost:8081") //指定具体ip允许跨域
public String hello() {
    return "hello world";
}

Author: stream
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source stream !
  TOC