由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。存在跨域的情况:
-
网络协议不同,如http协议访问https协议。
-
端口不同,如80端口访问8080端口。
-
域名不同,如cz1024.com访问gd1024.com。
-
子域名不同,如abc.cz1024.com访问def.cz1024.com。
-
域名和域名对应ip,如www.a.com访问196.1.18.163
由于我是搞服务端开发的就不说前端的事
服务端解决跨域的方法有二:
(1) nginx代理:(将跨域的源转为本域的源,绕过浏览器,然后由nginx替换真正的源,然后就可以请求了)
将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端。
实现方法:通过nginx代理;
注意点:1、如果你代理的是https协议的请求,那么你的proxy首先需要信任该证书(尤其是自定义证书)或者忽略证书检查,否则你的请求无法成功。
(2) cors
定义和用法:是现代浏览器支持跨域资源请求的一种最常用的方式。
使用方法:一般需要后端人员在处理请求数据的时候,添加允许跨域的相关操作。如下:
我这里是使用了springboot:
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 2允许任何请求头
corsConfiguration.addAllowedMethod("*"); // 3允许任何请求方法
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
这样确实是解决的跨域的问题,但是这个并不是很好,放在开发阶段没什么问题哈,如果正式发布的时候
corsConfiguration.addAllowedOrigin("*");中一定要写明你这个项目允许跨域访问的源,有多个就写多个这个方法,
它这里没有提供传接受集合的参数。(我这里只是说了最重要的源,其他参数也要考虑的)
另外一个说明下,我个人觉得springboot提供的这个东东方便好用但是不好理解(封装太多了),我们这里来看下直接手动实现过滤器来解决跨域问题。
@WebFilter(filterName = "corsFilter", urlPatterns = "/*",
initParams = {@WebInitParam(name = "allowOrigin", value = "*"),
@WebInitParam(name = "allowMethods", value = "GET,POST,PUT,DELETE,OPTIONS"),
@WebInitParam(name = "allowCredentials", value = "true"),
@WebInitParam(name = "allowHeaders", value = "Content-Type,X-Token")})
public class CorsFilter implements Filter {
private String allowOrigin;
private String allowMethods;
private String allowCredentials;
private String allowHeaders;
private String exposeHeaders;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
allowOrigin = filterConfig.getInitParameter("allowOrigin");
allowMethods = filterConfig.getInitParameter("allowMethods");
allowCredentials = filterConfig.getInitParameter("allowCredentials");
allowHeaders = filterConfig.getInitParameter("allowHeaders");
exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (!StringUtils.isEmpty(allowOrigin)) {
if(allowOrigin.equals("*")){
response.setHeader("Access-Control-Allow-Origin", allowOrigin);
}else{
List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
if (allowOriginList != null && allowOriginList.size() > 0) {
String currentOrigin = request.getHeader("Origin");
if (allowOriginList.contains(currentOrigin)) {
response.setHeader("Access-Control-Allow-Origin", currentOrigin);
}
}
}
}
if (!StringUtils.isEmpty(allowMethods)) {
response.setHeader("Access-Control-Allow-Methods", allowMethods);
}
if (!StringUtils.isEmpty(allowCredentials)) {
response.setHeader("Access-Control-Allow-Credentials", allowCredentials);
}
if (!StringUtils.isEmpty(allowHeaders)) {
response.setHeader("Access-Control-Allow-Headers", allowHeaders);
}
if (!StringUtils.isEmpty(exposeHeaders)) {
response.setHeader("Access-Control-Expose-Headers", exposeHeaders);
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
上面的@WebFilter用来配置过滤路径和一些参数,其他的就是规规矩矩的过滤器了,实际上就是给response添加各种请求头数据,给浏览器一些判断依据
其中懒得写个过滤器,过滤器代码来自:https://www.cnblogs.com/zkh101/p/7600726.html