Vue.js学习—— 分别从前后端Nginx解决SpringBoot+vue.js项目中的跨域问题
Posted 沧海一粟11
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue.js学习—— 分别从前后端Nginx解决SpringBoot+vue.js项目中的跨域问题相关的知识,希望对你有一定的参考价值。
一、什么是跨域
(1)跨域
由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一个与当前页面地址不同即为跨域。存在跨域的情况:
网络协议不同,如http协议访问https协议。 端口不同,如80端口访问8080端口。 域名不同,如qianduanblog.com访问baidu.com。 子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com。 域名和域名对应ip,如www.a.com访问20.205.28.90.
(2)url格式
一般格式:协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址
示例:https://www.dustyblog.cn:8080/say/Hello
是由https
+ www
+ dustyblog.cn
+ 8080
+ say/Hello
组成。
只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。
(3)Cors
CORS
全称为Cross Origin Resource Sharing
(跨域资源共享), 每一个页面需要返回一个名为Access-Control-Allow-Origin
的http头来允许外域的站点访问,你可以仅仅暴露有限的资源和有限的外域站点访问。
我们可以理解为:如果一个请求需要允许跨域访问,则需要在http头中设置Access-Control-Allow-Origin来决定需要允许哪些站点来访问。如假设需要允许https://www.dustyblog.c这个站点的请求跨域,则可以设置:
Access-Control-Allow-Origin:https://www.dustyblog.cn。
二、后端SpringBoot解决
1、方案一:CORS局部配置-使用@CrossOrigin注解
(1)在Controller
上使用@CrossOrigin
注解
该类下的所有接口都可以通过跨域访问
@RequestMapping("/demo2") @RestController //@CrossOrigin //所有域名均可访问该类下所有接口 @CrossOrigin("https://blog.csdn.net") // 只有指定域名可以访问该类下所有接口 public class CorsTest2Controller { @GetMapping("/sayHello") public String sayHello() { return "hello world --- 2"; } }
这里指定当前的CorsTest2Controller
中所有的方法可以处理https://csdn.net
域上的请求,其他域名不能请求
(2)在方法上使用@CrossOrigin
注解
@RequestMapping("/preUser") @CrossOrigin("https://blog.csdn.net")
public Map<String,String> preUser(){
Map<String,String> map = new HashMap<String,String>();
map.put("preUser","success");
return map;
}
这里指定只有该方法可以处理https://csdn.net
域上的请求,其他域名不能请求
2、方案二:CORS局部配置-手工设置响应头(局部跨域)
@RequestMapping("/hello") @ResponseBody public String index(HttpServletResponse response){ response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080"); return "Hello World"; }
Access-Control-Allow-Origin 表示允许哪些原始域进行跨域访问。 Access-Control-Allow-Credentials表示是否允许客户端获取用户凭据。 Access-Control-Allow-Methods 表示允许哪些跨域请求的提交方式。(例如GET/POST) Access-Control-Expose-Headers 表示允许暴露哪些头部信息给客户端。 Access-Control-Max-Age 表示预检请求 [Preflight Request] 的最大缓存时间。
3、方案三:CORS
全局配置-实现WebMvcConfigurer(本人习惯用法)
Spring Boot 2.0中已经废弃WebMvcConfigurerAdapter类, 开发人员可以通过实现WebMvcConfigurer
接口实现相应的功能。
CorsConfig.java
:/** * 跨域配置 */ @Configuration public class CorsConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**"). allowedOrigins("https://www.dustyblog.cn"). //允许跨域的域名,可以用*表示允许任何域名使用 allowedMethods("*"). //允许任何方法(post、get等) allowedHeaders("*"). //允许任何请求头 allowCredentials(true). //带上cookie信息 exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果 } }; } }
4、方案四:CORS
全局配置-使用Filter方式进行设置(过滤器实现)
通过实现Fiter
接口在请求中添加一些Header
来解决跨域的问题,向请求端设置Response Header(响应头部)的Access-Control-Allow-Origin属性声明允许跨域访问。
@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 { } }
5、方案五:CORS
全局配置-继承使用Spring Web中的CorsFilter
package com.garyond.hurricane.config; import org.springframework.stereotype.Component; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import java.util.Arrays; /** * 跨域访问配置 * * @author Garyond */ @Component public class CustomCorsFilter extends CorsFilter { public CustomCorsFilter() { super(configurationSource()); } private static UrlBasedCorsConfigurationSource configurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.setMaxAge(36000L); config.setAllowedMethods(Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/v1/**", config); return source; } }
或者
package com.ranxx.conf; 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; /** * 跨域问题 * * @author mousejoo */ @Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); // 1 允许任何域名使用 corsConfiguration.addAllowedHeader("*"); // 2 允许任何头 corsConfiguration.addAllowedMethod("*"); // 3 允许任何方法(post、get等) return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); // 4 return new CorsFilter(source); } }
或者
package com.example.longecological.config; 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 GlobalCorsConfig { @Bean public CorsFilter corsFilter() { //1.添加CORS配置信息 CorsConfiguration config = new CorsConfiguration(); //放行哪些原始域 config.addAllowedOrigin("*"); //是否发送Cookie信息 config.setAllowCredentials(true); //放行哪些原始域(请求方式) config.addAllowedMethod("*"); //放行哪些原始域(头部信息) config.addAllowedHeader("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) config.addExposedHeader("content-type"); //2.添加映射路径 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3.返回新的CorsFilter. return new CorsFilter(configSource); } }
三、前段Vue.js解决
解决方案:采用proxyTable
配置代理跨域
(1)打开项目根目录下的config/index.js
文件,参考以下proxyTable
部分的配置:
module.exports = {
dev: {
// Paths
assetsSubDirectory: ‘static‘,
assetsPublicPath: ‘/‘,
// *********代理跨域 主要代码**********
proxyTable: {
‘/api‘: { //匹配接口路径中的 /api,可以随意命名
target: ‘http://********:9001/api‘, //目标接口地址,设置调用的接口域名和端口号 别忘了加http、https
changeOrigin: true, //是否跨域
secure: true, // 允许https请求,https必须添加这个设置
pathRewrite: {
‘^/api‘: ‘‘ // 路径重写 将 target 中的目标接口地址重写为 /api,这里理解成用‘/api’代替target里面的地址,后面组件中我们掉接口时直接用api代替 比如我要调用‘http://40.00.100.100:3002/user/add‘,直接写‘/api/user/add’即可
} } }, }
注意:每次修改配置文件需要重启服务才能生效:npm run dev
(2)通过axios来实现发送访问
在main.js中导入已安装好的axios,并挂载到原型上
import Axios from ‘axios‘ //导入axios //将axios挂载到原型上 Vue.prototype.$axios = Axios;
(3)通过this.$axios.get().then()来实现数据请求
//发送get请求 show() { //用/api來代理‘http://localhost:8083‘ this.$axios .get("/api/selectall") .then(res => { this.list = res.data.result; // } }) .catch(e => { console.log(e); }); }, //发送post请求 add() { this.$axios({ method: "post", url: "/api/saveinfo", params: { name: this.name //传递的参数 } }).then(res => { this.show(); }); },
注意:此种跨域解决方案,只能适用于测试阶段,因为项目打包发布之后,由于proxyTable不能再使用,所以无法跨域了。正式环境中,前端项目和后端项目放在一起就不存在跨域问题了。如果非要跨域,则可以采取上面的后端解决方法或者下面的nginx替代前端的proxyTable代理功能。
三、Nginx解决生产环境跨域问题
1、安装好Nginx之后,打开安装目录下的conf/nginx.conf
文件,参考以下server
的简单配置:
server { listen 9091; #监听的端口 server_name localhost; #服务器名称 #charset koi8-r; #access_log logs/host.access.log main; location / { root E:hld-workuniversitydist; #项目物理路径 index index.html index.htm; #项目的默认首页 } location /api { #检测并替换接口内的字符串 proxy_pass http://**********:9001/api; #跨域访问的目标URL proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 100m; } }
注:每次修改配置文件需要重启服务才能生效
2、Nginx常用相关命令:
需要在Nginx文件目录下运行命令行工具
(1)启动
start nginx 或 nginx.exe
(2)停止
nginx.exe -s stop 或 ginx.exe -s quit
注:stop是快速停止nginx,可能并不保存相关信息;quit是完整有序的停止nginx,并保存相关信息。
(3)重新载入
nginx.exe -s reload
(4)重新打开日志文件
nginx.exe -s reopen
(5)查看版本
nginx -v
以上是关于Vue.js学习—— 分别从前后端Nginx解决SpringBoot+vue.js项目中的跨域问题的主要内容,如果未能解决你的问题,请参考以下文章
Heroku 部署混乱:Vue.js 前端与 Flask 后端
vue.js的“Firebase + Validation Example”中如何使用mysql作为数据持久化后端?