前后端分离解决跨域问题

什么是跨域

跨域是指从一个域名的网页去请求另一个域名的资源,域名、端口、协议任一不同,都算作跨域。

基于安全考虑,浏览器对于javascript的同源策略的限制。

前端跨域

我们前端项目中采用MVVM框架vue.js,2.0以后尤大推荐用axios与后台交互。

功能特性

  • 在浏览器中发送 XMLHttpRequests 请求
  • 在 node.js 中发送 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 自动转换 JSON 数据
  • 客户端支持保护安全免受 XSRF 攻击

vue cli脚手架搭建只需要在config目录下的index.js增加changeOrigin的配置即可

dev: {
    env: require('./dev.env'),
    port: 8080,
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        target: 'http://localhost:8004',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }

还需要注意的是,axios 默认是没有携带 cookie 的,如果后台项目是用 session 认证用户信息的话,每次请求的 sessionId 是不一样的。

需要在axios配置中将 withCredentials 设置为 true。

正式环境中,vue.js 代码会被 build 成 html 文件在 nginx 中部署,转发请求到后端服务。

  location /api/ {
        proxy_pass http://web-server/;
        proxy_connect_timeout 600;
        proxy_read_timeout 600;
    }

后端跨域

后端主要是通过跨域资源共享(CORS) 来实现允许跨域请求,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。

在 spring boot 中有两种跨域方式,在没有启用 spring security 时,直接在请求的controller层注解,类或者方法上都可以,其中 @CrossOrigin 中的2个参数:

  • origins : 允许可访问的域列表
  • maxAge:准备响应前的缓存持续的最大时间(以秒为单位)。
@CrossOrigin(origins = "http://www.baidu.com", maxAge = 3600)
@Api(tags = "数据源", description = "数据源业务类接口服务")
@RestController
@RequestMapping("/dataSource")
public class DataSourceAction {

    @Resource
    private DataSourceService service;

    @CrossOrigin()
    @ApiOperation("测试并保存数据源")
    @RequestMapping(value = "/saveDataSource", method = RequestMethod.POST)
    public void saveDataSource(@RequestParam Map<String, Object> map) throws Exception {
        service.testAndSave(map);
    }
}

也可以设置成全局

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author pilsy
 */
@Configuration
public class MiddlewareConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CorsMiddleware())
                .addPathPatterns("/**");
    }

    public class CorsMiddleware extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(
                HttpServletRequest request,
                HttpServletResponse response,
                Object handler
        ) throws Exception {
            if (request.getMethod().equals("OPTIONS")) {
                response.addHeader("Access-Control-Allow-Origin", "*");
                response.addHeader("Access-Control-Allow-Credentials", "true");
                response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS, DELETE");
                response.addHeader("Access-Control-Allow-Headers", "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,Authorization,If-Modified-Since,Cache-Control,Content-Type");
                response.addHeader("Access-Control-Max-Age", "3600");
                response.addHeader("charset", "utf-8");
            }
            return super.preHandle(request, response, handler);
        }
    }
}

在启用 spring security 后,由 security 管理跨域设置,首先实例化 CorsConfigurationSource

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(AllowedOrigins.getAllowedOrigin());
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("DNT", "X-Mx-ReqToken", "Keep-Alive", "User-Agent", "X-Requested-With", "Authorization", "If-Modified-Since", "Cache-Control", "Content-Type"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

再将 CorsConfigurationSource 注册到 security 配置项中

httpSecurity.cors().configurationSource(corsConfigurationSource());
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335