madworks
V2EX  ›  Java

vue 前端 springboot 后端分离跨域求解

  •  
  •   madworks · Oct 27, 2020 · 5239 views
    This topic created in 2198 days ago, the information mentioned may be changed or developed.
    上一周整合 springsecurity 写个项目,前端用 vue,302 跳转登录遇到跨域问题,一直无法解决,前后端都使劲浑身节数不得姐,不管用 @crossorigin,corsconfigaddorigin*、192168,前端设置 axiosCredentials,webpackproxy 都不行,求问怎么解决,还有问下大家是习惯 vue 前端打包后当成静态和后端放在一起运行,还是分开运行
    41 replies  •  2020-10-27 22:41:05 +08:00
    jiangnan01
    jiangnan01
    Oct 27, 2020
    1
    接口用 postman 能通吗?如果能通,前端在开发环境配 proxy 应该也是可以的,不需要后端做任何事
    至于到底是分开运行还是放到一起,看项目怎么要求了,能分开更好
    madworks
    madworks
    OP
    Oct 27, 2020
    2
    @jiangnan01 没有 postman,就是本地能用,用同事机器访问我 ip 项目不能
    jiangnan01
    jiangnan01
    Oct 27, 2020
    3
    @madworks 你自己运行起来是前后端分开的还是放在一起的?同事访问的方式呢?
    madworks
    madworks
    OP
    Oct 27, 2020
    4
    @jiangnan01 我自己访问是分开的,同事是访问我项目前端。而且我们另一个 vue 开发的项目发现 webpack 代理那里不能用 ip,必须写域名
    OldActorsSmile
    OldActorsSmile
    Oct 27, 2020
    5
    服务端 header 里配置允许跨域就好了,你看高德的 api,跨域调用它都没问题
    OldActorsSmile
    OldActorsSmile
    Oct 27, 2020
    6
    JAVA 我不熟,php 是这样写的:
    header('Access-Control-Allow-Origin:*'); // *代表允许任何网址请求
    hafuhafu
    hafuhafu
    Oct 27, 2020
    7
    盲猜可能是复杂请求没处理 OPTIONS 吧,跨域是浏览器的行为,如果接口本身是正常的,postman 不会管跨不跨域,肯定能通的。
    ljpCN
    ljpCN
    Oct 27, 2020 via Android
    8
    建议贴上完整的前端域名和 http 请求信息
    madworks
    madworks
    OP
    Oct 27, 2020
    9
    @OldActorsSmile 这个我写过,不行好像
    anonydmer
    anonydmer
    Oct 27, 2020
    10
    搞不定就搞个 nginx 代理下,去掉跨域啦
    madworks
    madworks
    OP
    Oct 27, 2020
    11
    @ljpCN 这个 springsecurity 代码里看到过,应该他内部已经做处理了
    jiangnan01
    jiangnan01
    Oct 27, 2020
    12
    @madworks 你自己的前端项目配 proxy 了吗?
    madworks
    madworks
    OP
    Oct 27, 2020
    13
    @jiangnan01 配了的
    OldActorsSmile
    OldActorsSmile
    Oct 27, 2020
    14
    @madworks

    跨域的原理是浏览器为了安全而阻止。如果浏览器发现服务器 header 告诉它允许就可以。高德的 api 跨域就是这个原理。
    有图有真相,你试试: https://shoujihao.zhishifufei.cn/

    THESDZ
    THESDZ
    Oct 27, 2020
    15
    1.本地调试,使用 proxyTable
    2.生产部署使用 nginx 反向代理到服务器 ip:port

    以上为本人解决方式,仅供参考
    NULL2020
    NULL2020
    Oct 27, 2020
    16
    ```

    @Override
    public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
    .allowedOrigins("*")
    .allowCredentials(true)
    .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
    .allowedHeaders("*");
    }


    ```
    KuroNekoFan
    KuroNekoFan
    Oct 27, 2020
    17
    没啥必要就置同域吧
    madworks
    madworks
    OP
    Oct 27, 2020
    18
    @NULL2020 这样写过,没用
    madworks
    madworks
    OP
    Oct 27, 2020
    19
    @THESDZ 加了一层,这样做的目的是什么
    THESDZ
    THESDZ
    Oct 27, 2020
    20
    @madworks 对于用户来说,前后端的资源请求在同一域内
    whatCanIDoForYou
    whatCanIDoForYou
    Oct 27, 2020
    21
    三种解决办法:
    1,nginx 配置映射 (我没有实操过。。)
    2,前端处理(我是后端)
    3,后端处理
    搞一个 配置类 或者配置文件(我是类)具体代码如下:
    @Configuration
    public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Bean
    public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration corsConfiguration = new CorsConfiguration();
    /*是否允许请求带有验证信息*/
    corsConfiguration.setAllowCredentials(true);
    /*允许访问的客户端域名*/
    corsConfiguration.addAllowedOrigin("*");
    /*允许服务端访问的客户端请求头*/
    corsConfiguration.addAllowedHeader("*");
    /*允许访问的方法名,GET POST 等*/
    corsConfiguration.addAllowedMethod("*");
    urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
    return new CorsFilter(urlBasedCorsConfigurationSource);
    }
    }
    wellsc
    wellsc
    Oct 27, 2020
    22
    配个反向代理?
    yaphets666
    yaphets666
    Oct 27, 2020
    23
    nginx 呀我的哥 webpack proxy 这就离谱了啊 这是前端自己启动 webpack-dev-server 开发的时候用的 执行 build 命令打包后的前端工程跟 webpack proxy 没关系了
    Sapp
    Sapp
    Oct 27, 2020❤️1
    24
    1. 试试 postman 这种可能不能跑通,没有下载就写个 node 调用一下看能不能通,能跑通就不是接口本身有问题
    2. 观察一下看看是不是 get 可以,post 不行,可能是复杂请求没有处理 option 的问题,如果都不行就不是这个问题
    3. 服务器设置一下允许跨域看看行不行,按理说这个是终极解决方案
    4. 如果服务器设置了跨域还是不行,那就继续检查一下 2 看看是不是没处理 option,理论上来讲,到这个阶段怎么都调用通了
    Sapp
    Sapp
    Oct 27, 2020
    25
    另外前端和后端是不是同域我觉得根本无所谓,现在跨域根本就不是个事,全看你们公司的架构怎么设计的前后端部署这一块。
    vision1900
    vision1900
    Oct 27, 2020
    26
    前端用 Proxy
    或者后端用个跨域中间件,没必要自己写,规则没有那么简单
    Express 这个中间件是 cors,一行代码解决战斗
    lzhlzhlc123
    lzhlzhlc123
    Oct 27, 2020
    27
    前端打包成静态之后可以使用 nginx 做静态资源代理代理
    可以在 nginx.conf 文件中下面添加 server 模块 ->server 模块中添加需要监听的端口号->server 中添加 location 模块中使用 root 和 index 做静态代理 location 中使用 proxy_set_header 做代理

    server {
    listen 85;
    location / {
    root /usr/local/app/hr/dist;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
    }

    location /api {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://localhost:8091/sxwendu;
    }
    }
    cco
    cco
    Oct 27, 2020
    28
    @CrossOrigin 注解- -。
    lzhlzhlc123
    lzhlzhlc123
    Oct 27, 2020
    29
    实在不行配合一下楼上兄弟的后端代码,基本可以解决大部分问题了
    clf
    clf
    Oct 27, 2020
    30
    前端代理就行,百度 Vue-cli 代理一大堆文章教程,或者弄个 nginx 搞反向代理 /api/ 到后端的端口路径。

    还有一种方法是前端代码 build 到后端的目录里,用 SpringBoot 作为静态文件服务器。
    ClutchBear
    ClutchBear
    Oct 27, 2020
    31
    spring security 好像是有自己的跨域解决方式:
    我是这样处理的
    在 SecurityConfig 中添加这个 bean
    ```
    /**
    * 跨域
    * https://lolico.me/2020/04/26/Spring-Security-CORS/
    * https://blog.csdn.net/Keith003/article/details/104221174
    *
    * @return
    */
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.addAllowedOrigin("*"); // 根据实际的需要去设置
    configuration.addAllowedMethod("*"); // 同上
    configuration.addAllowedHeader("*");
    configuration.setMaxAge(3600L);
    configuration.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
    }
    ```

    然后在重写的 configure 方法中, 添加
    ```
    // 禁用 CSRF
    http.csrf().disable();
    // 禁用表单登录
    http.formLogin().disable();
    // 防止 iframe 造成跨域
    http.headers().frameOptions().disable();
    // 开启跨域
    http.cors();
    ```

    在实现 AuthenticationFailureHandler 接口的 handler 中添加
    ```
    // 跨域 options 请求直接返回
    if (Objects.equals(request.getMethod(), HttpMethod.OPTIONS.toString())) {
    return;
    }
    ```
    bob971683
    bob971683
    Oct 27, 2020
    32
    同楼上,可以看下是不是请求的 OPTIONS 被验证拦截了
    hb0730
    hb0730
    Oct 27, 2020
    33
    /**
    * 创建跨域 filter
    *
    * @return {@link CorsFilter}
    */
    @Bean
    public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource corsConfiguration = new UrlBasedCorsConfigurationSource();
    corsConfiguration.registerCorsConfiguration("/**", build());
    return new CorsFilter(corsConfiguration);
    }

    private CorsConfiguration build() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowCredentials(true);
    configuration.addAllowedOrigin("*");
    configuration.addAllowedHeader("*");
    configuration.addAllowedMethod("*");
    configuration.addExposedHeader("content-disposition");
    configuration.setMaxAge(3600L);
    return configuration;
    }
    madworks
    madworks
    OP
    Oct 27, 2020
    34
    @lzhlzhlc123 已收藏,不过暂时不想引入 nginx
    youla
    youla
    Oct 27, 2020
    35
    如果是携带 cookies 跨域,应该不能这样写 Access-Control-Allow-Origin:*,要指定域名,如果有端口也要指定。

    如果不携带 cookies 跨域,axiosCredentials 设置为 false 就行了。
    lavvrence
    lavvrence
    Oct 27, 2020
    36
    kekxv
    kekxv
    Oct 27, 2020 via iPhone
    37
    有没有可能你请求的地址是 127.0.0.1
    Yourshell
    Yourshell
    Oct 27, 2020
    38
    框架配置好后,你先单独请求看看响应带不带跨域头啊,没有不就证明框架配置有问题么。
    EminemW
    EminemW
    Oct 27, 2020
    39
    首先跨域这玩意最好在 nginx 中配,不要侵入代码。。其次跨域头如果重复配,也会导致无法跨域,正常来说加这个 @crossorigin 注解就可以跨域的
    supuwoerc
    supuwoerc
    Oct 27, 2020
    40
    webpack proxy 打完包就没有用了,这玩意是开发的时候用的。

    一般都是塞到后端程序的项目里面,如果要分开的话一般都是 Nginx 代理。
    supuwoerc
    supuwoerc
    Oct 27, 2020
    41
    另外 postman 能通也没用。postman 又不是浏览器环境。

    跨域是浏览器的安全策略。postman 不存在这个策略。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   5078 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 70ms · UTC 07:54 · PVG 15:54 · LAX 23:54 · JFK 02:54
    ♥ Do have faith in what you're doing.