Доступ к ендпоинту без аунтификации, но по токену

Jmix version: 2.2.1

Здравствуйте!
К апи есть доступ по токену авторизации пользователя. Теперь надо добавить один ендпоинт, без авторизации пользователя но с проверкой apikey в хедере.

Как прикрутить правильно фильтр?

Заранее спасибо!

Здравствуйте.

Если такой контроллер у вас один, то самый простой способ - это открыть доступ к эндпойнту и внутри контроллера проверять наличие определённого заголовка.

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/mycontroller")
public class MyController {

    @GetMapping("/hello")
    public ResponseEntity<String> hello(@RequestHeader("X-Custom-Header") String customHeader) {
        if (!isHeaderValid(customHeader)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid header");
        }
        return ResponseEntity.ok("Hello");
    }

    private boolean isHeaderValid(String header) {
        return "valid".equals(header);
    }
}

Секьюрити конфигурация, которая “разрешает” наш эндпойнт. Обратите внимание, что её Order должен быть меньше, чем у JmixSecurityFilterChainOrder.FLOWUI, которая говорит, что все запросы должены быть authenticated.

import io.jmix.core.JmixSecurityFilterChainOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class MyControllerSecurityConfiguration {

    @Bean
    @Order(JmixSecurityFilterChainOrder.FLOWUI - 100)
    SecurityFilterChain myControllerSecurityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher("/mycontroller/**")
                .authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll());
        return http.build();
    }
}

Примерно так я и делал, но не взлетело. Так же и сейчас.
Ловлю ошибку org.springframework.security.access.AccessDeniedException: Access Denied

аннотация @AnonymousAllowed не помогает.
роль для ANONYMOUS выглядит так. без нее ругается на ее отсутствие

@ResourceRole(name = "ANONYMOUS", code = ANONYMOUSRole.CODE, scope = "API")

public interface ANONYMOUSRole {
    String CODE = "ANONYMOUS";

    @SpecificPolicy(resources = "rest.enabled")
    void specific();
}

Вот мой проект, на котором я проверял: controller-custom-auth-sample.zip (103.0 КБ)

Запрос:

curl --header "X-Custom-Header: valid" -v http://localhost:8080/mycontroller/hello

Попробуйте поменять мой проект, чтобы воспроизвелась ваша ошибка. Или сделайте собственный демо-проект, на котором ошибка воспрозводится. Иначе сложно что-то сказать.

Сначала подумал, что я просто не правильно запрос делал, а оказалось все таки был подводный камень.

Кейс такой
Есть несколько контроллеров которые начинаются как /api/…
Если контроллер, к которому я хочу открыть доступ, будет начинаться так-же, то случается ошибка.
А если к примеру apishecka/… то есть начало не будет совпадать с другими, тогда окей

У вас, возможно, стоит свойство типа

jmix.rest.authenticated-url-patterns=/api/**

Попробуйте в своей security конфигурации прописать вот такой Order для SecurityFilterChain

@Order(JmixSecurityFilterChainOrder.AUTHSERVER_RESOURCE_SERVER - 100) 

Тогда данный фильтр будет применяться до фильтра, который “защищает” ресурсы REST API.

1 симпатия

Ну почти, осталось разрешить доступ для Post метода, пока работает только с Get)

Попытка разрешить запрос на POST не удалась, запрос не пробивается и получаю 403.

Возможно, вам CSRF надо задисэйблить?

http
    // ..
    .csrf(csrf -> csrf.disable());