最近把我自己的网站升级生成前后端分离的项目(vue+springBoot),不可避免的就遇到了跨域问题。从中学到了许多知识,随便分享出来,也巩固下所学。

谈到跨域,首先得了解CORS(Cross origin resource sharing) 跨域资源共享,它是w3c的一个标准,是一份浏览器技术规范,提供了web服务从不同网域传来沙盒脚本的方法,以避免浏览器的同源策略,是比JSONP模式的高级版。JSONP只支持GET请求方式,而CORS除了GET请求方式以外也支持其他的HTTP请求。CORS允许浏览器发送跨域服务器,发出XMLHttpRequest请求,从而克服AJAX只能同源请求。(想要了解为什么有跨域问题的产生,请了解浏览器的同源策略)

浏览器发出CORS请求,需要对请求头增加一些信息,服务器会根据这些信息来是否决定同意这次请求。需要的头信息字段如下:

(1)Access-Control-Allow-Origin

这个头信息字段是必须的。它指定允许进入来源的域名、ip+端口号 。 如果值是 ‘*’ ,表示接受任意的域名请求,这个方式不推荐,主要是因为其不安全,而且因为如果浏览器的请求携带了cookie信息,会发生下图错误:

(2) Access-Control-Allow-Credentials

该字段是可选的。它设置是否可以允许发送cookie,true表示cookie包含在请求中,false则相反,默认为false。如果项目需要cookie就得设置该字段了。CORS请求默认不发送Cookie和HTTP认证信息的,所以在此基础上同时也需要在前端设置(以axios为例): axios.defaults.withCredentials = true

(3)Access-Control-Max-Age

该字段是可选的。用于配置CORS缓存时间,即本次请求的有效期,单位为秒。

(4)Access-Control-Allow-Methods

该字段可选。设置允许的请求方法。

(5)Access-Control-Allow-Headers

该字段可选。设置允许的请求头信息

(...)其他请参考相关资料

提示:这些设置在后端的拦截器中设置。

对于axios,它是vue2提倡使用的轻量版的ajax。它是基于promise的HTTP库。它会从浏览器中创建XMLHttpRequests。如果对axios不太了解,可以先看下这个两个博客:https://www.kancloud.cn/yunye/axios/234845    和   https://www.jianshu.com/p/7a9fbcbb1114

了解到这些之后就可以解决跨域问题啦, 详细代码如下:

(1) vue.js

import axios from 'axios'
import store from '../store'
import { getToken } from '@/utils/auth'
import { Message, MessageBox } from 'element-ui'
// 每次请求携带cookies信息
axios.defaults.withCredentials = true
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 15000 // 请求超时时间
})
// request拦截器
service.interceptors.request.use(config => {
console.log(store.getters.token)
if (store.getters.token) {
console.log(getToken())
config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
var token = getToken()
Object.assign(config.headers, { 'token': token })
}
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
})
// respone拦截器
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
console.log(response.data)
const res = response.data
if (res.code !== 20000) {
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})

// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
}
return null
} else {
return response.data
}
},
error => {
if (error.message === 'Network Error' && error.config.url.endsWith('/license')) {
Message({
message: '无法连接到本地代理程序,请确认代理程序是否运行正常!',
type: 'error',
duration: 5 * 1000
})
} else {
console.log(error + ' ' + error.config.url) // for debug
Message({
message: error.message + ' ' + error.config.url,
type: 'error',
duration: 5 * 1000
})
}
return Promise.reject(error)
}
)
export default service
 (2)springBoot

package xin.toheart.door.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@WebFilter(urlPatterns = { "/*" }, filterName = "loginAuthFilter")
public class LoginAuthFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(LoginAuthFilter.class);

@Override
public void destroy() {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse rep = (HttpServletResponse) response;
// 设置允许多个域名请求
String[] allowDomains = {"http://www.toheart.xin","http://192.168.10.213:8080","http://localhost:8080"};
Set allowOrigins = new HashSet(Arrays.asList(allowDomains));
String originHeads = req.getHeader("Origin");
if(allowOrigins.contains(originHeads)){
//设置允许跨域的配置
// 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
rep.setHeader("Access-Control-Allow-Origin", originHeads);
}

// 设置服务器允许浏览器发送请求都携带cookie
rep.setHeader("Access-Control-Allow-Credentials","true");
// 允许的访问方法
rep.setHeader("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE, PATCH");
// Access-Control-Max-Age 用于 CORS 相关配置的缓存
rep.setHeader("Access-Control-Max-Age", "3600");
rep.setHeader("Access-Control-Allow-Headers","token,Origin, X-Requested-With, Content-Type, Accept,mid,X-Token");
response.setCharacterEncoding("UTF-8");
// response.setContentType("application/json; charset=utf-8");
chain.doFilter(request, response);
}

@Override
public void init(FilterConfig arg0) throws ServletException {

}

}

axios解决跨域问题的更多相关文章

  1. axios解决跨域问题(vue-cli3.0)

    一.什么是跨域 1.跨域 指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制. 2.同源策略 是指协议,域名,端口都要相同,其中有一个不同都 ...

  2. 【VUE】vue在vue-cli3环境下基于axios解决跨域问题

    网上的绝大部分教程解决vue+axios跨域问题都不能直接适用vue-cli3.这是因为vue-cli3不一样的配置方式导致的. 如果是使用vue-cli3构建的项目,那么默认是没有config.js ...

  3. vue-cli3 axios解决跨域问题

    这种错误就是跨域问题: 我百度了各种方法,最终下面这种方法解决了,直接上代码:  解决: 如果没安装axios: npm install axios -save //安装axios main.js / ...

  4. Vue使用Axios实现http请求以及解决跨域问题

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中.Axios的中文文档以及github地址如下: 中文:https://www.kancloud.cn/y ...

  5. nuxt.js axios使用poxyTable代理,解决跨域问题

    1 安装(@gauseen/nuxt-proxy) cnpm install @gauseen/nuxt-proxy --save 2 配置nuxt.config.js modules: [ // 请 ...

  6. 【手摸手,带你搭建前后端分离商城系统】02 VUE-CLI 脚手架生成基本项目,axios配置请求、解决跨域问题

    [手摸手,带你搭建前后端分离商城系统]02 VUE-CLI 脚手架生成基本项目,axios配置请求.解决跨域问题. 回顾一下上一节我们学习到的内容.已经将一个 usm_admin 后台用户 表的基本增 ...

  7. 前端MVC Vue2学习总结(六)——axios与跨域HTTP请求、Lodash工具库

    一.axios Vue更新到2.0之后宣告不再对vue-resource更新,推荐使用axios,axios是一个用于客户端与服务器通信的组件,axios 是一个基于Promise 用于浏览器和 no ...

  8. 基于 HTTP 请求拦截,快速解决跨域和代理 Mock

    近几年,随着 Web 开发逐渐成熟,前后端分离的架构设计越来越被众多开发者认可,使得前端和后端可以专注各自的职能,降低沟通成本,提高开发效率. 在前后端分离的开发模式下,前端和后端工程师得以并行工作. ...

  9. Nginx反向代理和Node.js后端解决跨域问题

    最近在写自己的博客,涉及到跨域的问题,自己捣鼓许久,终于解决了.然后总结一下,记录一下,日后遇到类似的问题的时候也可以得到一些启发. 一.什么是跨域 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏 ...

随机推荐

  1. 基于Proxy的小程序状态管理

    摘要: 小程序状态管理. 作者:wwayne 原文:基于Proxy的小程序状态管理 Fundebug经授权转载,版权归原作者所有. 微信小程序的市场在进一步的扩大,而背后的技术社区仍在摸索着最好的实践 ...

  2. rt-thread can

    rt-thread stm32f10x-HAL can的驱动和应用.源码暂时还不支持,自己通过F4修改了一版 源码地址:https://gitee.com/gitee.thomas/rt_can rt ...

  3. 将流数据输出到Mysql中

    outputMysqlApp.scala import java.sql.DriverManager import org.apache.spark.SparkConf import org.apac ...

  4. 爬取70城房价到oracle数据库并6合1

    学习数据分析,然后没有合适的数据源,从国家统计局的网页上抓取一页数据来玩玩(没有发现robots协议,也仅仅发出一次连接请求,不对网站造成任何负荷) 运行效果 源码 python代码 ''' 本脚本旨 ...

  5. C++学习视频和资料

    我在学习c++时,比较迷茫,而且当时学完c++primer时不知道该学习什么, 犹豫了好久,最后找到了一些关于c++学习路线的视频,包含源代码,我感觉还不错,分享给大家. 下载地址 https://d ...

  6. 201871010109-胡欢欢《面向对象程序设计(java)》第6-7周学习总结

    实验六 继承定义与使用 实验时间 2019-9-29 第一部分:理论部分. 1.继承:已有类来构建新类的一种机制.档定义了一个新类继承另一个类时,这个新类就继承了这个类的方法和域,同时在新类中添加新的 ...

  7. 201871010117 石欣钰《面向对象程序设计(Java)》第十二周学习总结

      内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/ ...

  8. 201871010128-杨丽霞《面向对象程序设计(java)》第七周学习总

    201871010128-杨丽霞-<面向对象程序设计(java)>第七周学习总结 项目 内容 这个作业属于哪个课程  https://www.cnblogs.com/nwnu-daizh/ ...

  9. 【转载】深度解读 java 线程池设计思想及源码实现

    总览 开篇来一些废话.下图是 java 线程池几个相关类的继承结构: 先简单说说这个继承结构,Executor 位于最顶层,也是最简单的,就一个 execute(Runnable runnable) ...

  10. This server is in the failed servers list: localhost/127.0.0.1:16000 启动hbase api调用错误

    api 调用发现错误 Mon Nov 18 23:04:31 CST 2019, RpcRetryingCaller{globalStartTime=1574089469858, pause=100, ...