当前位置:   article > 正文

Vue之Axios跨域问题解决方案_axios解决跨域具体是怎么实现的

axios解决跨域具体是怎么实现的

背景:因为axios中只能使用get和post方法来进行请求数据,没有提供jsonp等方法进行跨域访问数据

          axios中文网址:https://www.kancloud.cn/yunye/axios/234845

  1. // axios 中的GET请求
  2. axios.get('/user', {
  3. params: {
  4. ID: ‘001
  5. }
  6. })
  7. .then(function (response) {
  8. console.log(response);
  9. })
  10. .catch(function (error) {
  11. console.log(error);
  12. });
  13. // axios 中的POST请求
  14. axios.post('/user', {
  15. firstName: '1',
  16. lastName: '2'
  17. })
  18. .then(function (response) {
  19. console.log(response);
  20. })
  21. .catch(function (error) {
  22. console.log(error);
  23. });

方案1:既然使用axios直接进行跨域访问不可行,我们就需要配置代理了。代理可以解决的原因:因为客户端请求服务端的数据是存在跨域问题的,而服务器和服务器之间可以相互请求数据,是没有跨域的概念(如果服务器没有设置禁止跨域的权限问题),也就是说,我们可以配置一个代理的服务器可以请求另一个服务器中的数据,然后把请求出来的数据返回到我们的代理服务器中,代理服务器再返回数据给我们的客户端,这样我们就可以实现跨域访问数据。

准备工作:安装所需中间件和插件等,比如axios,http-proxy-middleware等。

具体案例:这里以访问豆瓣Top250为例,直接访问如下:

  1. axios.get("http://api.douban.com/v2/movie/top250")
  2. .then(res=>{
  3. console.log(res)
  4. })
  5. .catch(err=>{
  6. console.log(err)
  7. })

当执行npm run dev时,控制台报错如下:

事实证明直接请求确实出现跨域问题了,下面具体演示解决跨域问题的步骤:

上面所说的必备条件都已安装完成的情况下,执行以下步骤即可解决问题:

1.配置BaseUrl

在main.js中,配置数据所在服务器的前缀(即固定部分),代码如下:

  1. // 项目入口,配置全局vue
  2. import Vue from 'vue'
  3. import VueRouter from './router/routes.js'
  4. import Store from './store/index.js'
  5. import './assets/less/index.less'
  6. import App from './App.vue'
  7. import ElementUI from 'element-ui'
  8. import 'element-ui/lib/theme-default/index.css'
  9. import axios from 'axios'
  10. Vue.prototype.$axios = axios
  11. axios.defaults.baseURL = '/api' //关键代码
  12. Vue.config.productionTip = false
  13. Vue.use(ElementUI);
  14. new Vue({
  15. router:VueRouter,
  16. store:Store,
  17. template:'<App/>',
  18. components: {App}
  19. }).$mount('#app')
  20. // 默认进入商品模块
  21. // VueRouter.push({ path: '/home' })

关键代码:axios.defaults.baseURL = '/api',作用是我们每次发送的请求都会带一个/api的前缀。

2.配置代理

在config文件夹下的index.js文件中的proxyTable字段中,作如下处理:

  1. dev: {
  2. env: require('./dev.env'),
  3. port: 8090,
  4. autoOpenBrowser: true,
  5. assetsSubDirectory: 'static',
  6. assetsPublicPath: '/',
  7. proxyTable: {
  8. '/api': {
  9. target:'http://api.douban.com/v2', // 你请求的第三方接口
  10. changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
  11. pathRewrite:{ // 路径重写,
  12. '^/api': '' // 替换target中的请求地址,也就是说以后你在请求http://api.douban.com/v2/XXXXX这个地址的时候直接写成/api即可。
  13. }
  14. }
  15. },
  16. // CSS Sourcemaps off by default because relative paths are "buggy"
  17. // with this option, according to the CSS-Loader README
  18. // (https://github.com/webpack/css-loader#sourcemaps)
  19. // In our experience, they generally work as expected,
  20. // just be aware of this issue when enabling this option.
  21. cssSourceMap: false
  22. }

3.在具体使用axios的地方,修改url如下即可:

  1. axios.get("/movie/top250").then((res) => {
  2. res = res.data
  3. if (res.errno === ERR_OK) {
  4. this.themeList=res.data;
  5. }
  6. }).catch((error) => {
  7. console.warn(error)
  8. })

4.重新启动项目之后,已经解决了跨域问题,结果如下:

原理:

因为我们给url加上了前缀/api,我们访问/movie/top250就当于访问了:localhost:8080/api/movie/top250(其中localhost:8080是默认的IP和端口)。

在index.js中的proxyTable中拦截了/api,并把/api及其前面的所有替换成了target中的内容,因此实际访问Url是http://api.douban.com/v2/movie/top250。

至此,纯前端配置代理解决axios跨域得到解决。

方案2:后端处理跨域问题,加个过滤器即可解决,如下:

  1. import javax.servlet.*;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. import java.io.IOException;
  5. /**
  6. * 跨域过滤器
  7. * @author jitwxs
  8. * @since 2018/10/16 20:53
  9. */
  10. public class CorsFilter implements Filter {
  11. @Override
  12. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  13. HttpServletResponse response = (HttpServletResponse) res;
  14. HttpServletRequest request = (HttpServletRequest) req;
  15. // 不使用*,自动适配跨域域名,避免携带Cookie时失效
  16. String origin = request.getHeader("Origin");
  17. if(StringUtils.isNotBlank(origin)) {
  18. response.setHeader("Access-Control-Allow-Origin", origin);
  19. }
  20. // 自适应所有自定义头
  21. String headers = request.getHeader("Access-Control-Request-Headers");
  22. if(StringUtils.isNotBlank(headers)) {
  23. response.setHeader("Access-Control-Allow-Headers", headers);
  24. response.setHeader("Access-Control-Expose-Headers", headers);
  25. }
  26. // 允许跨域的请求方法类型
  27. response.setHeader("Access-Control-Allow-Methods", "*");
  28. // 预检命令(OPTIONS)缓存时间,单位:秒
  29. response.setHeader("Access-Control-Max-Age", "3600");
  30. // 明确许可客户端发送Cookie,不允许删除字段即可
  31. response.setHeader("Access-Control-Allow-Credentials", "true");
  32. chain.doFilter(request, response);
  33. }
  34. @Override
  35. public void init(FilterConfig filterConfig) {
  36. }
  37. @Override
  38. public void destroy() {
  39. }
  40. /*
  41. 注册过滤器:
  42. @Bean
  43. public FilterRegistrationBean registerFilter() {
  44. FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
  45. bean.addUrlPatterns("/*");
  46. bean.setFilter(new CorsFilter());
  47. // 过滤顺序,从小到大依次过滤
  48. bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
  49. return bean;
  50. }
  51. */
  52. }

以上axios解决跨域的方案,希望能解决大家遇到的跨域问题,如有问题请添加评论。

-------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------

根据评论区内容,区分一下生产环境和开发环境,集体配置如下:

1.在config文件夹里面创建一个api.config.js的配置文件

  1. const isPro = Object.is(process.env.NODE_ENV, 'production')
  2. console.log(isPro);
  3. module.exports = {
  4. baseUrl: isPro ? 'https://www.***/index.php/Official(线上地址)' : 'api/'
  5. }

2.在main.js文件里面引入上面文件,这样就可以保证动态的匹配生产和开发环境的定义前缀了,代码如下:

  1. import Vue from 'vue'
  2. import App from './App'
  3. import router from './router'
  4. import 'bootstrap/dist/js/bootstrap.min'
  5. import 'bootstrap/dist/css/bootstrap.min.css'
  6. import axios from 'axios'
  7. import apiConfig from '../config/api.config'
  8. Vue.prototype.$axios = axios;
  9. Vue.config.productionTip = false;
  10. axios.defaults.baseURL = apiConfig.baseUrl;// 配置接口地址
  11. axios.defaults.withCredentials = false;

以上两步即可解决vue的跨域问题,并且可以可以直接build打包到线上,如有问题,请评论区留言,希望对你有所帮助。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/266032
推荐阅读
相关标签
  

闽ICP备14008679号