web-dev-qa-db-ja.com

春のセキュリティでセッションが見つからなかったため、提供されたCSRFトークンを確認できませんでした

Java configと共にspring securityを使用しています

@Override
protected void configure(HttpSecurity http) throws Exception { 
    http
    .authorizeRequests()
    .antMatchers("/api/*").hasRole("ADMIN")
    .and()
    .addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class)
    .exceptionHandling()
    .authenticationEntryPoint(restAuthenticationEntryPoint)
    .and()
    .formLogin()
    .successHandler(authenticationSuccessHandler)
    .failureHandler(new SimpleUrlAuthenticationFailureHandler());

RESTサービスのテストにPostManを使用しています。 「csrfトークン」を正常に取得し、リクエストヘッダーでX-CSRF-TOKENを使用してログインできます。しかし、ログイン後、ポストリクエストをヒットすると(ログインポストリクエストに使用したものと同じトークンをリクエストヘッダーに含めています)、次のエラーメッセージが表示されます。

HTTPステータス403-セッションが見つからなかったため、提供されたCSRFトークンを確認できませんでした。

誰かが私が間違っていることを私に導くことができますか?.

40
Haseeb Wali

Spring.ioによると:

いつCSRF保護を使用すべきですか?通常のユーザーがブラウザで処理できるリクエストにはCSRF保護を使用することをお勧めします。ブラウザ以外のクライアントが使用するサービスのみを作成する場合は、CSRF保護を無効にすることをお勧めします。

それを無効にするには:

@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
  }
}

注: CSRF保護は、Java構成でデフォルトで有効になっています

72
Derick

これを試してください:@Override protected boolean sameOriginDisabled() { return true;}

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    ...

    // Determines if a CSRF token is required for connecting. This protects against remote
    // sites from connecting to the application and being able to read/write data over the
    // connection. The default is false (the token is required).
    @Override
    protected boolean sameOriginDisabled() {
        return true;
    }
}

ソース: WebSocketセキュリティ:WebSocket内でCSRFを無効化

3
GuoJunjun

CSRF保護を無効にすることは悪い考えです。

Springは各リクエストの後に新しいCSRFトークンを自動的に生成し、副作用(PUT, POST, PATCH, DELETE).を持つすべてのHTTPリクエストにそれを含める必要があります

Postmanでは、各リクエストでテストを使用して、CSRFトークンをグローバルに保存できます。 CookieCsrfTokenRepositoryを使用する場合

pm.globals.set("xsrf-token", postman.getResponseCookie("XSRF-TOKEN").value);

そして、キーX-XSRF-TOKENと値{{xsrf-token}}を持つヘッダーとしてそれを含めます。

2
Dario Seidl

POSTメソッドで同じエラーが発生し、「セッションが見つからなかったため、提供されたCSRFトークンを検証できませんでした」という403 Forbiddenが発生していました。

@EnableResourceServerアノテーションをconfigに追加して、解決策を見つけた後、時間をかけました。

構成は次のようになります(spring-boot.version-> 1.4.1.RELEASE、spring-security.version-> 4.1.3.RELEASE、spring.version-> 4.3.4.RELEASE)

@Configuration
@EnableWebSecurity
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends ResourceServerConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.userDetailsService(inMemoryUserDetailsManager()).passwordEncoder(passwordEncoder());
}

@Override
public void configure(HttpSecurity http) throws Exception {
    http.httpBasic();
    http.sessionManagement().sessionCreationPolicy(STATELESS);
    http.csrf().disable();
    http.authorizeRequests().anyRequest()
            .permitAll();
}

private InMemoryUserDetailsManager inMemoryUserDetailsManager() throws IOException {
    // load custom properties
    Properties properties = new Properties();
    return new InMemoryUserDetailsManager(properties);
}

private PasswordEncoder passwordEncoder() {
    return new TextEncryptorBasedPasswordEncoder(textEncryptor());
}

private TextEncryptor textEncryptor() {
    return new OpenSslCompatibleTextEncryptor();
}

}
0
Dmitri Algazin

JS fetch AJAXをHTTP Status 403 - Could not verify the provided CSRF token because your session was not found.オプションを使用せずに呼び出すと、このエラーメッセージ(credentials: "same-Origin")が表示されます。

間違った方法

fetch(url)
.then(function (response) { return response.json(); })
.then(function (data) { console.log(data); })

正しい方法

fetch(url, {
    credentials: "same-Origin"
})
.then(function (response) { return response.json(); })
.then(function (data) { console.log(data); })
0

これは古い質問ですが、誰かを助けるかもしれません。私は同様の問題を抱えていたが、これは私がそれを解決することができた方法です。

CSRFがREST AP​​Iと連携するには、すべての呼び出しの前にAPIを介してCSRFトークンを取得し、そのトークンを使用する必要があります。トークンは毎回異なり、再利用できません。

CSRFトークンを取得するコントローラーは次のとおりです。

@RequestMapping(value = "/csrf", method = RequestMethod.GET)
    public ResponseEntity<CSRFDTO> getCsrfToken(HttpServletRequest request) {
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        return ResponseEntity.ok(CSRFDTO.builder()
                .headerName(csrf.getHeaderName())
                .token(csrf.getToken())
                .build());
    }

また、Springアプリを構成して、REST AP​​IエンドポイントのCSRFを無効にすることを検討することもできます。私がどこかで読んだ記事を引用するには:

RESTエンドポイント上のCSRFトークンが追加の保護を許可しないことは確かです。そのため、RESTエンドポイントでCSRF保護を有効にすると、アプリケーションに無駄なコードが導入されるだけで、スキップする必要があると思います。

お役に立てれば。

0
Parthanaux