当前位置: 首页 > 知识库问答 >
问题:

CSRF问题,同时将POST请求从Angular 2发送到Spring支持的Java应用程序

江烨伟
2023-03-14

我使用Angular 2和基于Java的后端编写UI,在Spring Security性的基础上使用OpenID Connect身份验证。

身份验证工作正常,但仅适用于GET请求。每次在资源上执行POST、PUT或DELETE方法时,我都会得到HTTP 403:

{
  "status": 403,
  "message": "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.",
}

我这样使用HttpClient:

http.post(
    '/api/my-resource',
    JSON.stringify(myObject),
    new RequestOptions({
        headers: new Headers({'Content-Type': 'application/json'})
    })
)

当我添加与凭据:真到请求选项这里建议我仍然得到HTTP 403,但与不同的消息:

{
  "status": 403,
  "message": "Could not verify the provided CSRF token because your session was not found.",
}

我需要做什么才能使HttpClient与CSRF一起工作?

注:我还研究了类似的问题,特别是angular-2-spring-security-csrf-implementation-problems,但提出的解决方案并不能解决我的问题。同时,我不想禁用CSRF。

共有2个答案

龙弘济
2023-03-14

使用spring boot 2.2.2(spring security 5.2.1)和Angular 8.2.14,此配置对我适用:

  @NgModule({
  declarations: [],
  imports: [
    BrowserModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions({cookieName: 'XSRF-TOKEN'}),

与Radouane的更新响应相同的配置。

但是对于Spring靴部分:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf()
         .csrfTokenRepository(cookieCsrfTokenRepository())
         .and()
         .authorizeRequests()
         .antMatchers("/static/**").permitAll()
         ...
         .anyRequest().authenticated();
}

private CookieCsrfTokenRepository cookieCsrfTokenRepository() {

    final CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
    cookieCsrfTokenRepository.setCookiePath("/");
    return cookieCsrfTokenRepository;
}

根据这个回答,

仅当XSRF-TOKEN cookie是使用以下选项在服务器端生成时,Angular才会添加X-XSRF-TOKEN标头:

Path = /
httpOnly = false

此外,Angular应用程序和被调用的URL必须位于同一服务器上。

诸葛亮
2023-03-14
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions({cookieName: 'XSRF-TOKEN'})
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

添加CSRFcookie配置,如下所示:

@NgModule({
    declarations: [declarations],
    imports: [imports],
    providers:
    [
        {provide: XSRFStrategy, useFactory: xsrfFactory}
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

export function xsrfFactory() {
    return new CookieXSRFStrategy('XSRF-TOKEN', 'XSRF-TOKEN');
}

并使用正确的头名称配置Spring Security性。

    private static final String CSRF_HEADER_NAME = "XSRF-TOKEN";

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            ...
            .and()
                .csrf()
                    .ignoringAntMatchers(CSRF_IGNORE)
                    .csrfTokenRepository(csrfTokenRepository())
            .and()
               .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName(CSRF_HEADER_NAME);
        return repository;
    }

其中CsrfHeaderFilter:

public class CsrfHeaderFilter extends OncePerRequestFilter {

    private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());

        if (csrf != null) {

            Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);
            String token = csrf.getToken();

            if (cookie == null || token != null && !token.equals(cookie.getValue())) {
                cookie = new Cookie(CSRF_COOKIE_NAME, token);
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }

        filterChain.doFilter(request, response);
    }
}
 类似资料:
  • 问题内容: 我有一个非常简单的应用程序(没有Spring Boot)。我已经实现了和控制器方法。该方法效果很好。但是,POST正在抛出。复制步骤如下 ServiceController. java AppConfig.java AppInitializer.java 该代码在这里可用: 这将旋转嵌入式tomcat。 现在你可以卷曲以下内容 工作良好 但 引发415不支持的MediaType 问题答

  • 我想从php发送post请求到python并得到答案,我写了这个脚本发送post 我使用定制python服务器

  • 问题内容: 让我们假设这个网址… (此处的ID需要在POST请求中发送) 我想将其发送到服务器的,该服务器在POST方法中接受它。 如何在Java中执行此操作? 我尝试了这个: 但是我仍然不知道如何通过POST发送 问题答案: 由于原始答案中的某些类已在Apache HTTP Components的较新版本中弃用,因此,我将发布此更新。 顺便说一句,你可以在此处访问完整的文档以获取更多示例。

  • 我有过 拍照。py:从网络摄像头拍摄照片的Python脚本 如何发送拍摄的照片。是否通过POST请求复制到Flask应用程序? TakePhoto.py 应用程序。派克

  • 我正在编写一个控制器来处理来自AJAX的帖子。我一直收到一个错误,那篇文章不受支持。我以前在尝试创建后控制器方法时从未遇到过以下错误,我希望有人能发现我在哪里搞砸了。 这是我为控制控制器中的帖子而编写的方法: 使用JQuery 1.10,这是请求它的Ajax调用: 我知道POST地址是正确的,因为将它转换成GET请求就可以了。此外,我还编写了其他POST请求,它们在同一个控制器类中也能正常工作。任

  • login.jsp 用户列表.jsp AppController.java 有2页:login.jsp-起始页,其中包括与登录和密码填充的形式-userlist.jsp结果列表“显示数据库中所有用户持久化”..首先显示登录页面,当我单击提交按钮时,我得到了这个错误:org . spring framework . web . servlet . pagenotfound-不支持请求方法“POST”