@ Защищенные аннотации не работают в режиме AspectJ с Autoproxy
Я пытаюсь заставить мое приложение Spring MVC хорошо играть с аннотациями Spring @Secured и автоматическим проксированием AspectJ, но, похоже, оно не проксирует или не распознает мои аннотации @Secured. У меня есть контроллер, как это:
@Controller
@RequestMapping("/")
public class ApplicationController {
private ApplicationFactory applicationFactory;
@Inject
public ApplicationController(ApplicationFactory applicationFactory) {
super();
this.applicationFactory = applicationFactory;
}
@Secured("ROLE_USER")
@ResponseBody
@RequestMapping(method = GET)
public Application getApplicationInfo() {
return applicationFactory.buildApplication(this);
}
}
И пружинный XML-код безопасности, который выглядит примерно так:
Код:
<security:global-method-security secured-annotations="enabled" mode="aspectj" proxy-target-class="true" />
<security:http auto-config="true" use-expressions="true">
<security:http-basic/>
</security:http>
Вышеуказанное загружается компонентом no-xml Spring @Configuration следующим образом:
@Configuration
@ComponentScan(basePackages = {"com.example"})
@EnableWebMvc
@ImportResource("classpath:security.xml")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
}
Который, в свою очередь, загружается с использованием Servlet 3.0 WebApplicationInitializer:
public class SpringMvcInitializer implements WebApplicationInitializer {
private final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
public void onStartup(ServletContext servletContext) throws ServletException {
context.register(ApplicationConfiguration.class);
servletContext.addListener(new ContextLoaderListener(context));
servletContext.addListener(new Log4jConfigListener());
final DelegatingFilterProxy proxy = new DelegatingFilterProxy("springSecurityFilterChain", context);
FilterRegistration.Dynamic filter = servletContext.addFilter("securityFilter", proxy);
filter.addMappingForUrlPatterns(EnumSet.of(REQUEST), false, "/*");
final DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
}
Однако Spring Security не обнаруживает аннотацию, и я все еще могу использовать защищенную конечную точку, указанную выше, без авторизации. Согласно Spring Security FAQ, это может быть потому, что <global-method-security>
Элемент загружается в неправильном контексте приложения, но я не знаю, как это обеспечить, используя вышеупомянутую конфигурацию Spring без no-xml.
Я что-то пропустил? Я попытался добавить @EnableAspectJAutoProxy(proxyTargetClass = true) в конфигурацию моего приложения, но это тоже не помогло. Есть ли в любом случае переплетение времени выполнения или мне придется использовать переплетение времени компиляции для обеспечения безопасности на основе аннотаций для моего приложения?
2 ответа
При использовании AOP с Spring вы можете выбрать одну из двух реализаций AOP:
Реализация Spring AOP не требует ткачества, но она применима только к bean-компонентам, управляемым Spring, и имеет некоторые ограничения
Реализация AspectJ AOP может работать для всех объектов и не имеет ограничений Spring AOP, но требует переплетения во время компиляции или загрузки
mode="aspectj"
говорит Spring использовать AspectJ для реализации AOP, поэтому аспект безопасности не будет работать без переплетения в вашем случае.
Термин "автоматическое проксирование AspectJ" не имеет ничего общего с использованием AspectJ в качестве реализации AOP - это функция, которая позволяет использовать AspectJ API (а не реализацию) с Spring AOP.
Итак, в вашем случае вы можете использовать реализацию Spring AOP, потому что контроллер - это bean-компонент Spring, поэтому вы должны удалить mode="aspectj"
, Также обратите внимание, что ваш контроллер должен иметь конструктор без аргументов - это одно из ограничений Spring AOP.
Чтобы немного расширить ответ @axtavt, mode="aspectj"
вариант в global-method-security
конкретно требует, чтобы ваш код был сплетен с AnnotationSecurityAspect
от spring-security-aspects
модуль.
Есть некоторый пример кода, который демонстрирует его использование. Он состоит только из защищенного компонента и некоторого теста Junit, но код компилируется с помощью компилятора AspectJ. Контекст приложения также показывает, насколько просто он сравнивается с тем, что требовалось до того, как была добавлена поддержка пространства имен (закомментированные компоненты).