Подтвердить что ты не робот

Не удалось проверить предоставленный токен CSRF, потому что ваш сеанс не найден в spring безопасности

Я использую spring безопасность вместе с java config

@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());

Я использую PostMan для тестирования моих служб REST. Я получаю "csrf token" успешно, и я могу войти с помощью X-CSRF-TOKEN в заголовке запроса. Но после входа в систему, когда я удаляю пост-запрос (я включаю тот же токен в заголовок запроса, который я использовал для запроса на вход в систему). Я получаю следующее сообщение об ошибке:

Статус HTTP 403 - Не удалось проверить предоставленный токен CSRF, потому что ваш сеанс не найден.

Может ли кто-нибудь объяснить мне, что я делаю неправильно.

4b9b3361

Ответ 1

По словам spring.io:

Когда следует использовать защиту от CSRF? Мы рекомендуем использовать защиту CSRF для любого запроса, который может быть обработан браузером обычными пользователями. Если вы создаете только службу, которая используется не браузерными клиентами, вы, вероятно, захотите отключить защиту CSRF.

Итак, чтобы отключить его:

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

Примечание. Защита CSRF включена по умолчанию в конфигурации Java.

Ответ 2

Отключение защиты CSRF - плохая идея.

Spring автоматически генерирует новый токен CSRF после каждого запроса, и вам необходимо включить его во все HTTP-запросы с побочными эффектами (PUT, POST, PATCH, DELETE).

В Postman вы можете использовать тест в каждом запросе для хранения токена CSRF в глобальном, например, при использовании CookieCsrfTokenRepository

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

А затем {{xsrf-token}} его в качестве заголовка с ключом X-XSRF-TOKEN и значением {{xsrf-token}}.

Ответ 3

попробуйте это: @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 Security: отключить CSRF в WebSockets

Ответ 4

У меня была та же проблема, тот же результат: "Не удалось проверить предоставленный токен CSRF, потому что ваш сеанс не был найден".

Но, в моем случае, я делаю два запроса, а второй запрос (POST) не работает.

Код здесь:

private List<Mandado> pesquisaExterna(Pessoa pessoa) throws UnsupportedEncodingException, IOException, URISyntaxException {
        this.httpClient = HttpClientBuilder.create().build();
        /* Estabelecendo a Sessão */
        Gson gson = new Gson();

        this.httpContext = HttpClientContext.create();
        CookieStore cookieStore = new BasicCookieStore();
        this.httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);


        HttpPost post_auth = new HttpPost(this.URL_AUTENTICAR); // URL para request
        StringEntity postingString = new StringEntity(gson.toJson(this.authenticationRequestDTO)); // Objeto para POST
        post_auth.setEntity(postingString);

        post_auth.addHeader("content-type", MediaType.APPLICATION_JSON_VALUE); // definindo os headers
        post_auth.addHeader("cache-control", "no-cache");
        System.out.println("body: " + gson.toJson(this.authenticationRequestDTO));

        HttpResponse response;

        ObjectMapper mapper = new ObjectMapper();
        AuthenticationResponseDTO auth = new AuthenticationResponseDTO();

        String cookie = "";
        String result = "";

        try {
            response = this.httpClient.execute(post_auth, this.httpContext);
            String resp = MandadoBusiness.convertStreamToString(response.getEntity().getContent());
            System.out.println("resp1: " + resp);

            JsonNode authentication = mapper.readTree(resp);

            PessoaFilter filter = new PessoaFilter();

            if (pessoa.getNrCpf() != null && pessoa.getNrCpf().length() == 11) {
                DocumentoDTO doc = new DocumentoDTO();
                doc.setNumero(pessoa.getNrCpf());
                filter.setDocumento(doc);
            }


            List<NameValuePair> postParameters = new ArrayList<>(); //parâmetros do request
            postParameters.add(new BasicNameValuePair("page", "1"));
            postParameters.add(new BasicNameValuePair("size", "30"));

            URIBuilder uriBuilder = new URIBuilder(this.URL + "/api/pessoas/filter");
            uriBuilder.addParameters(postParameters);

            HttpPost post = new HttpPost(uriBuilder.build()); // URL para request

            postingString = new StringEntity(gson.toJson(filter)); // Objeto para POST
            post.setEntity(postingString);

            post.addHeader("content-type", MediaType.APPLICATION_JSON_VALUE); // definindo os headers
            post.addHeader("Cookie", authentication.get("token_csrf").asText());
            post.addHeader("X-XSRF-TOKEN", authentication.get("token_csrf").asText());
            post.addHeader("Authorization", "Bearer " + authentication.get("token_jwt").asText());

            // IMPRESSÃO DOS DETALHES DO REQUEST FEITO
            System.out.println("body: " + gson.toJson(filter));
            System.out.println("headers: " + Arrays.toString(post.getAllHeaders()));
            System.out.println("request_line: " + post.getRequestLine().toString());

            response = this.httpClient.execute(post,this.httpContext);

            if(response.getEntity() != null){
                result = MandadoBusiness.convertStreamToString(response.getEntity().getContent());
                System.out.println("Response: " + result);
            }else{
                System.out.println("Response with error!!");
            }

        } catch (IOException | UnsupportedOperationException e) {
            System.out.println("Msg: " + e.getMessage());
        }

        return gson.fromJson(result, ArrayList.class);
    }

Кто-то может помочь - мне понять ошибку?

Пожалуйста, извините за мой ужасный английский!

Ответ 5

Приходил к той же ошибке только с методами POST, получал 403 Запрещено "Не удалось проверить предоставленный токен CSRF, потому что ваш сеанс не был найден".

Изучив некоторое время, нашел решение, добавив аннотацию @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();
}

}

Ответ 6

Я получаю это сообщение об ошибке (HTTP Status 403 - Could not verify the provided CSRF token because your session was not found.), Когда я выполняю вызов AJAX JS для выборки без использования параметра 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); })

Ответ 7

Я решил это, добавив последний атрибут на мою страницу входа, возможно, это будет выгодно.

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"  isELIgnored="false"%>