解决跨域问题

4 篇文章 0 订阅

什么是跨域问题

跨域是是因为浏览器的同源策略限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。
所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域。

一句话讲明白就是:浏览器不允许你在一个网页内请求另一个不同源的链接

这些是知乎上的解释:

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。 在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问问题。在请求的过程中我们要想回去数据一般都是post/get请求,所以会出现跨域问题。 出于浏览器的同源策略限制。

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

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

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

跨域问题的解决方法

后端解决:使用 cors

cors是跨域资源共享,是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。服务端设置了Access-Control-Allow-Origin就开启了CORS,所以这种方式只要后端实现了CORS,就解决跨域问题,前端不需要配置。

使用该方式的特点:与前两种方式相比,前端代码和未处理跨域前一样,即普通的 ajax 请求,但服务器代码添加了一段解决跨域的代码。

springboot 解决跨域问题:

1. CrossOrigin注解
//@CrossOrigin  表示所有的URL均可访问此资源
@CrossOrigin(origins = "http://127.0.0.1:8093")//表示只允许这一个url可以跨域访问这个controller
@RestController
@RequestMapping("/testCorss")
public class CorssOriginController {

    //可以对方法运用该注解
    //@CrossOrigin(origins = "http://127.0.0.1:8093")
    @GetMapping("/getString")
    public String getString(){
        return "跨域成功!";
    }
}

代码说明:@CrossOrigin这个注解用起来很方便,这个可以用在方法上,也可以用在类上。如果你不设置他的value属性,或者是origins属性,就默认是可以允许所有的URL/域访问。

  • value属性可以设置多个URL。
  • origins属性也可以设置多个URL。
  • maxAge属性指定了准备响应前的缓存持续的最大时间。就是探测请求的有效期。
  • allowCredentials属性表示用户是否可以发送、处理 cookie。默认为false
  • allowedHeaders 属性表示允许的请求头部有哪些。
  • methods 属性表示允许请求的方法,默认get,post,head。

这个视频讲了注解的方法,可以看一下。

此方式虽然虽然实现(跨域)比较简单,但你应该也发现了,使用此方式只能实现局部跨域,当一个项目中存在多个类的话,使用此方式就会比较麻烦(需要给所有类上都添加此注解)。


2. 实现WebMvcConfigurer

接下来我们通过设置配置文件的方式就可以实现全局跨域了,它的实现步骤如下:

  • 创建一个新配置文件 implements WebMvcConfigurer;

  • 添加 @Configuration 注解,实现 WebMvcConfigurer 接口;

  • 重写 addCorsMappings 方法,设置允许跨域的代码。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
@Configuration // 一定不要忽略此注解
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 所有接口
                .allowCredentials(true) // 是否发送 Cookie
                .allowedOriginPatterns("*") // 支持域
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) // 支持方法
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/testCross/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowCredentials(true)
                .allowedOrigins("http://localhost:8093")
                .maxAge(2000);
    }
}

这个没什么好说的,就重写addCorsMappings方法就行,配置好参数,参数和上面的注解的参数类似。这个配置属于全局配置,配置好了全部的接口都遵循此规则。上面的注解方式只对类或者方法生效。addMaping是设置对那种格式的URL生效,也就是跟在URL后面的路径。


3. 过滤器配置

此实现方式和上一种实现方式类似,它也可以实现全局跨域,它的具体实现代码如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
 
@Configuration // 一定不能忽略此注解
public class MyCorsFilter {
    @Bean
    public CorsFilter corsFilter() {
        // 1.创建 CORS 配置对象
        CorsConfiguration config = new CorsConfiguration();
        // 支持域
        config.addAllowedOriginPattern("*");
        // 是否发送 Cookie
        config.setAllowCredentials(true);
        // 支持请求方式
        config.addAllowedMethod("*");
        // 允许的原始请求头部信息
        config.addAllowedHeader("*");
        // 暴露的头部信息
        config.addExposedHeader("*");
        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 3.返回 CorsFilter 对象
        return new CorsFilter(corsConfigurationSource);
    }
}
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class Filter {
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:8093");//*表示允许所有
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }

}

利用过滤器配置实现跨域,还有另外一种方法

package com.example.democrossorigin.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
public class CorssFilter 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", "http://localhost:8093");
        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");
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

参考链接:Spring Boot 解决跨域问题的 5种方案


前端解决:代理服务器

我用的这种方法,虽然不太清楚原理但是成功部署了。

首先在开发环境下,你需要在vue.config.js中配置代理:

proxy: {
      '/api': { // 定义了一个代理路径,表示以 /api 开头的请求将会被代理转发
        // 指定了代理请求的目标地址,即后台的真实接口地址。这里目标地址是 http://localhost:8080/,
        // 即代理服务器会将以 /api 开头的请求转发到这个地址。
        target: process.env.VUE_APP_URL, 
        ws: false,
        secure: false,
        changeOrigin: true, // 表示启用跨域,允许代理服务器发送带有源 origin(请求的源地址)的请求
        pathRewrite:{
          // 浏览器发送的 /api/core/getData/userInfo 请求,代理服务器会将该请求的地址重写为 http://localhost:8080/core/getData/userInfo
          // 并将重写后的请求转发给真实的后台接口地址,即把 /api 换成了空字符串
          '^/api':''
        }
      }
    },

然后你的生产环境就不会出现跨域问题了。

当你的项目打包部署到 Nginx 服务器上时,你还要配置 Nginx 服务器的代理。在 Nginx 的文件夹下

  • 点击exe启动
  • 打包后的项目放 /html 里面
  • /logs 里面有报错信息
  • /conf/nginx.conf 里面修改配置信息

浏览器直接访问 http://localhost:80/ 就可以了,要修改端口改配置信息的这里:

在这里插入图片描述

后端服务器的地址是 http://localhost:8080/ ,前端项目通过代理服务器的方式解决跨域问题,所以将打包后的文件放到 /html 里面后,还要修改代理服务器。

我修改了配置文件中的这里:

在这里插入图片描述

参考链接:

vue项目部署服务器跨域处理(nginx)_本地测试不跨域,服务器上跨域

vue项目生产环境使用/api跨域,怎么部署到Nginx上 - 搜索 (bing.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值