CSRF 令牌未正确更新(Ionic + Spring Security)

Posted

技术标签:

【中文标题】CSRF 令牌未正确更新(Ionic + Spring Security)【英文标题】:CSRF Token not updated properly (Ionic + Spring Security) 【发布时间】:2020-07-19 19:53:01 【问题描述】:

我正在使用 Ionic Framework 开发一个应用程序,并为我的后端生成了一个 JHipster 项目。我的 JHipster 项目在额外的服务器上运行,并通过我的应用程序的 REST 请求调用。所以我现在的问题是处理 CORS 和 CSRF 配置。

我的 JHipster 项目有自己的前端,它在同一个域上运行,并且在测试时我可以毫无问题地访问我的后端。但是,当我想从 Ionic 应用程序调用服务器上的后端时,我的 xsrf 令牌不会正确更新,因此我无法访问我的后端。我已经尝试了来自不同堆栈溢出帖子的几种解决方案,但没有一个对我有用。

例如:

Ionic using CORS and CSRF

Could not verify token

https://github.com/angular/angular/issues/18859

到目前为止我做了什么:

    我在我的 JHipster 项目的 SecurityConfiguration 中启用了 csrf
        http
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
            .authenticationEntryPoint(problemSupport)
            .accessDeniedHandler(problemSupport)
    添加了 CORS 配置
  cors:
    allowed-origins: 'http://localhost:8100, ionic://localhost, http://localhost'
    allowed-methods: 'POST, GET, OPTIONS, DELETE, PUT, HEAD'
    allowed-headers: 'Origin, X-Requested-With, Content-Type, Accept, x-auth-token, Authorization, X-CSRF-Token, x-xsrf-token, XSRF-TOKEN'
    exposed-headers: 'Authorization,Link,X-Total-Count,XSRF-TOKEN, X-XSRF-TOKEN'
    allow-credentials: true
    max-age: 86400
    写了一个拦截器
@Injectable()
export class HttpXSRFInterceptor implements HttpInterceptor 

  constructor(private tokenExtractor: HttpXsrfTokenExtractor, private csrfService:CSRFService,  private $sessionStorage: SessionStorageService) 
  

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    const headerName = 'XSRF-TOKEN';
    const respHeaderName = 'X-XSRF-TOKEN';
    let token = this.tokenExtractor.getToken() as string;

    if (token !== null && !req.headers.has(headerName)) 
      req = req.clone( headers: req.headers.set(respHeaderName, token) );
      req.clone(
        withCredentials: true
      );
    
    return next.handle(req);
  

    在我的 app.module.ts 和拦截器中添加了 HttpClientXsrfModule
    HttpClientXsrfModule.withOptions(
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-XSRF-TOKEN',
    ),
    
      provide: HTTP_INTERCEPTORS,
      useClass:  HttpXSRFInterceptor,
      multi: true
    ,

我的问题:

在浏览器中启动我的应用程序时,我没有获得 xsrf 令牌,但是在我发送发布请求后,令牌被设置为 cookie。

例如登录时,由于缺少令牌,第一次尝试失败,但第二次登录请求成功,因为现在 xsrf 令牌的响应标头不再为空。此外,即使服务器响应的标头中有新令牌,令牌也不会自行更新。

据我了解

    我第一次获得我的令牌应该是在加载我的应用程序的起始页面之后立即

    应在服务器(后端)每次响应后更新令牌,并将更新后的令牌用于下一个请求

因此我的问题是这两个问题都没有发生,我不知道如何解决它。

感谢您的帮助!

干杯

【问题讨论】:

【参考方案1】:

我是 JHipster 的 Ionic 的作者,所以希望我能帮助你。

首先,CSRF 不应该成为问题除非您在同一个端口上运行您的应用程序。根据我的经验,当您在单独的端口上运行它们时,您的客户端无法读取 cookie。至于CORS,在本地运行时这对我来说不是问题。我相信这是因为 dev 配置文件的 CORS 设置是完全开放的。您可以尝试在prod 个人资料中使用dev 个人资料中的设置,看看是否有帮助?

供参考,它们是:

jhipster:
  cors:
    allowed-origins: '*'
    allowed-methods: '*'
    allowed-headers: '*'
    exposed-headers: 'Authorization,Link,X-Total-Count'
    allow-credentials: true
    max-age: 1800

如果可行,我会尝试将您允许的来源更改为一个数组,或者只使用一个。如果在本地运行,http://localhost:8100 应该是你所需要的。

【讨论】:

如果可行,我会尝试将您允许的来源更改为数组: 所以我尝试按照您的建议更改我的 cors 设置,但我得到“在请求参数 '_csrf' 或标头 'X-XSRF-TOKEN' 上找到了无效的 CSRF 令牌 'null'”作为响应信息。也许我理解错了,但是如果我在 localhost:8080 上测试我的后端并在 localhost:8100 上测试我的离子应用程序,我会因为不同的端口而遇到问题?还是因为我在与 ionic 应用程序不同的域上运行后端而导致配置出现问题?

以上是关于CSRF 令牌未正确更新(Ionic + Spring Security)的主要内容,如果未能解决你的问题,请参考以下文章

Django - 403 Forbidden - CSRF 令牌丢失或不正确

Spring Boot - Spring Security CSRF 保护未在登录页面中注入令牌

直接访问登录表单时未设置会话 cookie,导致 CSRF 令牌无效

api 端点未在 Sanctum 上进行 CSRF 令牌验证 - CSRF 令牌不匹配

CSRF 令牌未激活

通知未广播到控制台?