首页 > 解决方案 > 从 Nginx 提供 Spring REST API,CORS 和 CSRF 的问题

问题描述

我已经为此苦苦挣扎了 8 个小时,我意识到这不是我自己能想到的。

我正在尝试在 DigitalOcean Ubuntu 上使用 Nginx 提供使用 Spring Boot 实现的 REST API。我已经实现了一个简单的 JWT 身份验证以及在每个请求上传递一个 CSRF 令牌。我有一个用 ReactJS 实现的前端。当我将它部署到 Heroku 时,整个系统运行良好,但当时后端也服务于前端,所以 CORS 真的不是什么大问题。我应该为“客户端”进行部署,他的 webhotel 不支持 Spring Boot,因此我需要在不同的位置提供前端和后端服务。

基本上我遇到了多个问题:

我一直在谷歌搜索并尝试不同类型的配置,以至于我什至不知道我的修复是否真的导致了更多问题,或者只是没有做任何事情。

我的 Spring 安全配置

        http
                .csrf()
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                    .and()
                .requiresChannel()
                    .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
                    .requiresSecure()
                    .and()
                .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler)
                    .and()
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                .authorizeRequests()
                    .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                    .antMatchers("/api/auth/**").permitAll()
                    .antMatchers("/static/**").permitAll()
                    .antMatchers("/**").permitAll()
                    .anyRequest().authenticated();

Spring CORS 配置

        registry.addMapping("/**")
                .allowedOrigins([URL to the frontend for testing purposes])
                .allowedMethods("GET", "POST", "OPTIONS", "DELETE", "PUT", "PATCH")
                .allowedHeaders("authorization, content-type, content-length, xsrf-token, credentials")
                .allowCredentials(true)
                .exposedHeaders("xsrf-token")
                .maxAge(3600);

Nginx 服务配置

server {
        listen 443 ssl;
        listen [::]:443 ssl;
        include snippets/self-signed.conf;
        include snippets/ssl-params.conf;

        server_name [IP of my DigitalOcean droplet here];

        location /api {
             proxy_pass http://localhost:8080/api;
             proxy_set_header Origin [URL to the frontend deployed on Heroku for testing purposes];
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header X-Forwarded-Proto $scheme;
             proxy_set_header X-Forwarded-Port $server_port;
             proxy_pass_header X-XSRF-TOKEN;
        }
}

server {
    listen 80;
    listen [::]:80;

    server_name [IP of my DigitalOcean droplet here];

    return 302 https://$server_name$request_uri;
}

前端的axios配置

  const CSRF_TOKEN = document.cookie.match(new RegExp('XSRF-TOKEN=([^;]+)'))[1];

  instance = axios.create({
    withCredentials: true,
    baseURL: '[ip-address of my DigitalOcean droplet]/api',
    headers: { 
      'X-XSRF-TOKEN': CSRF_TOKEN,
      'Access-Control-Allow-Methods': 'PATCH, DELETE, POST, GET, OPTIONS, PUT'
    }
  });

我在这里非常初学者,所以我什至不确定这是否正确。我只知道当它全部部署到 Heroku 时它起作用了,所以至少其中一些应该是正确的。

标签: reactjsspring-bootnginxspring-security

解决方案


推荐阅读