После работы с различными структурами безопасности я решил go с Apache Shiro для моего Spring Boot RestAPI, потому что он, кажется, предлагает необходимую гибкость без слишком больших бюрократических c накладных расходов. До сих пор я ничего не делал, кроме добавления зависимости maven в свой проект:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.5.1</version>
</dependency>
Это заставило меня определить bean-компонент Realm для запуска приложения:
@Bean
public Realm realm() {
return new TMTRealm();
}
Бин почти ничего не делает, кроме реализации интерфейса Realm:
public class TMTRealm implements Realm {
private static final String Realm_Name = "realm_name";
@Override
public String getName() {
return Realm_Name;
}
@Override
public boolean supports(AuthenticationToken token) {
return false;
}
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
return null;
}
}
Пока все хорошо. За исключением того, что теперь мой RestAPI нарушает политику CORS, не добавляя заголовок «Access-Control-Allow-Origin» в любой его ответов. Я заметил, что Chrome не отправляет какой-либо выделенный запрос OPTIONS, но два запроса одного и того же метода, в данном случае GET, с ошибкой первого из них выглядит следующим образом:
Access to XMLHttpRequest at 'http://localhost:8081/geo/country/names?typed=D&lang=en-US' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Без Shiro его представляет работает отлично, как элегантный способ использования аннотации Spring @CrossOrigin на контроллере, так и грубый метод старой школы определения bean-компонента CorsFilter:
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("OPTIONS", "GET", "POST", "PUT", "DELETE"));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
Я реализовал интерфейс SpringL ApplicationListener для перехвата в то время, когда ApplicationContext запускается и может видеть, что bean-компонент corsFilter зарегистрирован и присутствует:
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("############ - application context started with beans: ");
final String[] beans = event.getApplicationContext().getBeanDefinitionNames();
Arrays.parallelSort(beans);
for (final String bean : beans) {
System.out.println(bean);
}
}
Вывод:
...
conditionEvaluationDeltaLoggingListener
conventionErrorViewResolver
corsFilter
countryController
...
Но фильтр никогда не вызывается при любом запросе (я установил точку останова и System.out, чтобы доказать это). Я также заметил, что присутствуют три боба Широ:
shiroEventBusAwareBeanPostProcessor
shiroFilterChainDefinition
shiroFilterFactoryBean
Поэтому я предполагаю, что, вероятно, shiroFilterFactoryBean как-то ломает его и требует дополнительного внимания и настройки. К сожалению, документация Apache Shiro, похоже, ничего не говорит о запросах между источниками, и я предполагаю, что это (не обязательно) часть проблем безопасности Shiro, а скорее базовый Restful API, то есть Spring. Поиск в Google не принес никаких полезных результатов, поэтому я подозреваю, что я упускаю что-то большое или, что еще хуже, что-то маленькое и очевидное. Пока я пытаюсь это выяснить, любая помощь или подсказка очень ценится, спасибо!