代码之家  ›  专栏  ›  技术社区  ›  ssc-hrep3

JHipster:CORS在表单登录时失败(实际请求,而不是飞行前)

  •  16
  • ssc-hrep3  · 技术社区  · 7 年前

    我想用第二个前端应用程序扩展jHipster的整体设置,该应用程序从不同的URL访问相同的API。作为第一步,我在 application.yml 我从前端发送请求 withCredentials

    许多方法现在都能如期工作,但并非全部。飞行前( OPTIONS 请求)始终按预期进行并工作。此调用的响应包含正确的CORS标头。

    然而,实际请求(例如登录的POST请求)也需要标头( Access-Control-Allow-Origin /api/authentication /api/logout /api/account (仅当未登录时, 401 ,之后,它在正确的标题下按预期工作)

    例如,对于注销,Google Chrome会在控制台中显示以下消息,即使呼叫在网络选项卡中通过( POST

    http://localhost:8080/api/logout . 请求的资源上不存在“Access Control Allow Origin”标头。原点' http://localhost:9000 因此不允许访问。

    AjaxAuthenticationSuccessHandler ),但这似乎并不正确。

    我用的是非常过时的jHipster版本 3.7.0 . 然而,我宁愿不更新核心项目。

    你知道是什么导致了这个问题吗?



    标题

    /api/注销 选项 调用按预期工作,但在 访问控制允许原点

    选项 要求

    OPTIONS /api/logout HTTP/1.1
    Host: localhost:8080
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Access-Control-Request-Method: POST
    Origin: http://localhost:9000
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
    Access-Control-Request-Headers: x-csrf-token
    Accept: */*
    DNT: 1
    Referer: http://localhost:9000/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,de-CH;q=0.2,it;q=0.2

    选项 回答

    HTTP/1.1 200 OK
    Access-Control-Allow-Headers: x-csrf-token
    Date: Mon, 11 Sep 2017 13:54:57 GMT
    Connection: keep-alive
    Access-Control-Allow-Origin: http://localhost:9000
    Vary: Origin
    Access-Control-Allow-Credentials: true
    Content-Length: 0
    Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
    Access-Control-Max-Age: 1800

    要求

    POST /api/logout HTTP/1.1
    Host: localhost:8080
    Connection: keep-alive
    Content-Length: 0
    Pragma: no-cache
    Cache-Control: no-cache
    Accept: application/json, text/plain, */*
    Origin: http://localhost:9000
    X-CSRF-TOKEN: [***token removed in this snippet***]
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
    DNT: 1
    Referer: http://localhost:9000/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,de-CH;q=0.2,it;q=0.2
    Cookie: [***removed cookies in this snippet***]

    岗位 回答

    HTTP/1.1 200 OK
    Expires: 0
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Set-Cookie: CSRF-TOKEN=null; path=/; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:00 GMT
    Set-Cookie: JSESSIONID=[***removed jsessionID in this snippet***]; path=/; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:00 GMT
    Set-Cookie: remember-me=null; path=/; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:00 GMT
    X-XSS-Protection: 1; mode=block
    Pragma: no-cache
    Date: Mon, 11 Sep 2017 13:54:57 GMT
    Connection: keep-alive
    X-Content-Type-Options: nosniff
    Content-Length: 0

    生殖

    this demo project of jHipster in version 3.7.0 src/main/resources/application.yml . 之后,在上创建一个新用户 localhost:8080 并激活它。最后,尝试从另一个端口(例如简单节点服务器或xampp)使用以下JS代码段进行身份验证。你也可以试着做一个简单的 呼叫 /api/账户 错误有关错误消息,请参阅Google Chrome控制台。

    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.js"></script>
    <script type="text/javascript">
    var Http = axios.create({
      baseURL: 'http://localhost:8080/api',
    });
    
    Http.interceptors.request.use(function (config) {
      config.xsrfCookieName = 'CSRF-TOKEN';
      config.xsrfHeaderName = 'X-CSRF-TOKEN';
      config.withCredentials = true;
      return config;
    });
    
    var credentials = {
      username: 'test-user',
      password: 'test123',
      rememberMe: true
    };
    
    Http.post('authentication', 'j_username=' + credentials.username +
    '&j_password=' + credentials.password +
    '&remember-me=' + credentials.rememberMe +
    '&submit=Login');
    </script>
    2 回复  |  直到 7 年前
        1
  •  5
  •   Jon Ruddell    7 年前

    看起来你遇到了 this CORS issue 其中 CorsFilter Spring Security的过滤链抛出了一个错误。请求从未到达 CorsFilter公司 ,导致响应中缺少CORS标头。这就是为什么Chrome抱怨控制台中缺少标题,尽管这是另一个错误。

    你需要把 CorsFilter公司 CsrfFilter UsernamePasswordAuthenticationFilter 因此,如果这些过滤器中的任何一个出现问题,响应仍然会获得CORS头。要实现这一点,请将以下代码添加到 SecurityConfiguration.java :

    // import CorsFilter
    import org.springframework.web.filter.CorsFilter;
    ...
    ...
    // inject for JHipster v3 apps, add to constructor for JHipster v4 apps
    @Inject
    private CorsFilter corsFilter;
    ...
    ...
    // add this line in the configure method before ".exceptionHandling()"
    .addFilterBefore(corsFilter, CsrfFilter.class)
    

    也在 ,您可以设置 @EnableWebSecurity(debug = true) 查看每个请求的过滤链。您可以通过确保 用户名密码身份验证过滤器

    Security filter chain: [
        WebAsyncManagerIntegrationFilter
        SecurityContextPersistenceFilter
        HeaderWriterFilter
        CorsFilter     <--------- Before CsrfFilter and UsernamePasswordAuthenticationFilter
        CsrfFilter
        CsrfCookieGeneratorFilter
        LogoutFilter
        UsernamePasswordAuthenticationFilter
        RequestCacheAwareFilter
        SecurityContextHolderAwareRequestFilter
        RememberMeAuthenticationFilter
        AnonymousAuthenticationFilter
        SessionManagementFilter
        ExceptionTranslationFilter
        FilterSecurityInterceptor
    ]
    

    如果您在新客户端中遇到CSRF问题,您可能需要在发布后发出GET请求以刷新CSRF令牌。可以看到JHipster如何处理这一问题的示例 when logging out

        2
  •  3
  •   Julien Dubois    7 年前

    看看 org.springframework.web.cors.CorsConfiguration Spring bean在 JHipster common application properties . 我认为您缺少以下配置行:

    exposed-headers: "Authorization"

    also added this configuration by default a few hours ago .

    Separating the front-end and the API server