Jmix version: 2.2.1
Здравствуйте!
К апи есть доступ по токену авторизации пользователя. Теперь надо добавить один ендпоинт, без авторизации пользователя но с проверкой apikey в хедере.
Как прикрутить правильно фильтр?
Заранее спасибо!
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.
Ну почти, осталось разрешить доступ для Post метода, пока работает только с Get)
Попытка разрешить запрос на POST не удалась, запрос не пробивается и получаю 403.