Spring #CacheEvict not working - java

I've experience in Spring MVC, but first time using Cache. These are steps that I've done yet.
Step : 1
// In spring config
#Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("user");
}
// Cached Object
public class CachedUser {
private String username;
private String token;
// Public getter-setter
}
// AuthServiceImp
#Service
public class AuthServiceImp implements AuthService {
#Override
#Cacheable(value="user", key="#token")
#Transactional
public CachedUser loadUserDetailsFromDb(String username, String token) {
// codes here
}
#Override
#CacheEvict(value="user", key="#token")
#Transactional
public void removeUser(String username, String token) {
// codes here
}
}
// My Filter
public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter {
AuthService authService = WebApplicationContextUtils
.getRequiredWebApplicationContext(this.getServletContext())
.getBean(AuthService.class);
CachedUser user = this.authService.loadUserDetailsFromDb(username, authToken);
}
// Controller
#RestController
public class AuthenticationController {
#Autowired
private AuthService authService;
#GetMapping("logout2")
public ResponseModel logout(#RequestAttribute("username") String username,
HttpServletRequest request) {
String token = request.getHeader(tokenHeader);
authService.removeUser(username, token);
return new ResponseModel(200,"Success",null);
}
}
Whenever calling loadUserDetailsFromDb from AuthenticationTokenFilter it returns cached object (except in first call obviously). That means #Cacheable(value="user", key="#token") is working fine.
But even after I logged out and called authService.removeUser(), calling loadUserDetailsFromDb() fetches the cached object. That means #CacheEvict(value="user", key="#token") is not working.
Step: 2
Referred this and moved removeUser() to another service ( say CacheServiceImp implements CacheService ), yet same problem.
Step: 3
Reffered this and , by my understanding, moved #Cache* annotation to interface AuthService, got following error.
java.lang.IllegalArgumentException: Null key returned for cache
operation (maybe you are using named params on classes without debug
info?)
Note : Is the problem of not evicting, because I'm calling #Cacheable and #CacheEvict methods from different classes. That is from AuthenticationTokenFilter and AuthenticationController

After playing with my code, head and internet, at last, I got this solved. It's a mistake in my Spring (Security) configuration, which I failed to post with the question.
Mistake 1 :
In SecurityInitializer class
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
public SecurityInitializer() {
super(WebSecurityConfiguration.class);
}
}
As the project includes Spring MVC configuration, the constructor must not be implemented. So removed the constructor. This class, then, simply registers the springSecurityFilterChain Filter for every URL.
Mistake 2: ( THE REAL CAUSE OF ABOVE PROBLEM )
I've added my AuthenticationTokenFilter in two ways:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// other overrides
#Override
protected Filter[] getServletFilters() {
return new Filter[]{ new AuthenticationTokenFilter() };
}
}
and
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
// Other config
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
//Other config
httpSecurity.addFilterBefore(authTokenFilter,
UsernamePasswordAuthenticationFilter.class);
}
}
This made the filter to be called twice, one inside Spring context and the other as usual Servlet filter
So removed configuration inside WebAppInitializer
Additional change
Removed #ComponentScan from WebSecurityConfiguration because it's already in SpringMvcConfig. This requires both configurations to be loaded in same context. Done by following code.
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringMvcConfig.class, WebSecurityConfiguration.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
// Removed filter registering from here (Mistake 2)
}
At last, everything working FINE :)

Related

How to enforce 1 Bean instance and avoid NoUniqueBeanDefinitionException?

I'm implementing a websocket service where incoming messages are passed to controllers and the controllers can then broadcast response messages to another websocket session(s).
When they broadcast the message back, there is either 1 of 2 issues. Either MySocketHandler is a different instance than the one that handled afterConnectionEstablished (using Autowired annotation on MySocketHandler in MessageRouter seems to create a new instance) or I get NoUniqueBeanDefinitionException (if I use ApplicationContext to specifically get the bean by class type).
An instance of my application should only have 1 MySocketHandler, so I annotated MySocketHandler with #Scope(ConfigurableBeanFactory.SCOPE_SINGLETON).
I suspect this has something to do with asynchronous event publishing and listening. I've refactored this code a few times to try to implement this the "Spring" way but there's some fundamental error each time.
I want to know how I can enforce the Spring container to create and reuse only 1 instance of MySocketHandler.
Here is my a minimalized version of MySocketHandler.java to exemplify the problem:
#Component
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class MySocketHandler extends BinaryWebSocketHandler {
#Autowired private ApplicationContext applicationContext
#Autowired private MessageRouter messageRouter;
private final HashMap<String, WebSocketSession> sessions = new HashMap<>();
#EventListener
public void onOutgoingBinaryMessageEvent(OutgoingBinaryMessageEvent event) {
// ERROR: NoUniqueBeanDefinitionException
applicationContext.getBean(MySocketHandler.class).broadcast(event.getBytes(), event.getConnectionIds());
}
#Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.put(session.getId(), session);
}
#Override
public void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
eventPublisher.publishEvent(new IncomingBinaryMessageEvent(
this,
message.getPayload().array(),
session.getId()));
}
private void broadcast(byte[] bytes, Set<String> playerIds) {
BinaryMessage binaryMessage = new BinaryMessage(bytes);
// this.sessions is null because its a different instance of MySocketHandler than the one that actually managing the connections
for (WebSocketSession session : sessions.values()) {
try {
webSocketSession.sendMessage(binaryMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And an example of the MessageRouter.java:
#Component
public class MessageRouter {
#Autowired private ApplicationEventPublisher eventPublisher;
public void send(Message message) {
eventPublisher.publishEvent(message);
}
#EventListener
private void routeMessageToController(SomeMessageEvent any, String connectionId) {
.....
// Parse message and route it to a controller class.
.....
}
}
}
Application entry point:
public class MyApplication implements WebSocketConfigurer {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(getSocketHandler(), "/").setAllowedOriginPatterns("*");
}
#Bean
public MySocketHandler getSocketHandler() {
return new MySocketHandler();
}
}
An instance of my application should only have 1 MySocketHandler, so I
annotated MySocketHandler with
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON).
First of all , singleton is applied in the bean level but not the type level. It can't ensure your application will only has the single bean of a particular type. You can still define multiple singleton bean for the same type.
In most general cases , a bean can be defined by the following ways:
Annotating the class with #Component (or its specialisation version such as #Repository , #Service , #Controller , #Configuration etc.)
Using #Bean method in the #Configuration class
Now you are doing :
#Component
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class MySocketHandler extends BinaryWebSocketHandler
}
#SpringBootApplication
public class MyApplication implements WebSocketConfigurer {
#Bean
public MySocketHandler getSocketHandler() {
return new MySocketHandler();
}
}
Note: #SpringBootApplication is a composed annotation which contain #Configuration
which means you are now defining two MySocketHandler beans . One with the name mySocketHandler (defined via #Component) and the other has the name getSocketHandler (defined via #Bean)
So to ensure there is only one MySocketHandler bean , either remove #Component from MySocketHandler or remove this #Bean method.

Dependency Injection into Spring Servlet context (OncePerRequestFilter)

I implemented a OncePerRequestFilter, where in the doFilterInternal() I would like to use an utilization class, that used JdbcTemplate and user data from a properties file. I realized that it couldn't reach the data from the properties file (database connection and variables) and has null value all the time. As I found on the internet it's, because of the different context.
I could successfully setup a new jdbc datasource locally, but I wouldn't like to duplicate the code, so I would like to inject simply the sources the same way as I did everywhere else like in RestControllers (#Value, #Autowired).
Any idea, how could I inject these in my utilization class that will be used in the servlet filter or directly in my filter?
Thank you!
UPDATE - code snippets:
In the RestController, the injection of JdbcTemplate works properly, but in the filter I cannot inject it, always throws nullPointerException.
#SpringBootApplication
public class AsdApplication {
public static void main(String[] args) {
SpringApplication.run(AsdApplication.class, args);
}
public static class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Filter[] getServletFilters() {
DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
delegateFilterProxy.setTargetBeanName("MyFilter");
return new Filter[] { delegateFilterProxy };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return null;
}
}
}
#RestController
public class RestCtrl {
#Autowired
private JdbcTemplate jdbcTemplate;
#GetMapping("/test")
public ResponseEntity<String> getTest() {
String result = jdbcTemplate.queryForObject("<query>", String.class);
System.out.println("result in ctrl: " + result);
return new ResponseEntity<>("asd ad asd asd asd", HttpStatus.OK);
}
}
#Component(value = "MyFilter")
public class MyFilter extends OncePerRequestFilter {
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String result = jdbcTemplate.queryForObject("<query>", String.class);
System.out.println("result in filter: " + result);
User currentUser = new User("username", "password", new ArrayList<>());
UsernamePasswordAuthenticationToken authenticatedUser = new UsernamePasswordAuthenticationToken(
currentUser, null, currentUser.getAuthorities()
);
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
filterChain.doFilter(request, response);
}
}
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests().anyRequest().authenticated();
httpSecurity.addFilterBefore(new MyFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
spring.datasource.url=jdbc:<sqlserver>
spring.datasource.username=<user>
spring.datasource.password=<pass>
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
As you are actually using Spring Boot and want to make it part of the Spring Security filter chain (which is something different!) what you need to do is
Create an #Bean method to create the filter and make it a bean
Create an #Bean method and add a FilterRegistration bean to prevent the bean from being registered as a filter by Spring Boot
Configure Spring Security.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests().anyRequest().authenticated();
httpSecurity.addFilterBefore(myFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
#Bean
public MyFilter myFilter() {
return new MyFilter();
}
#Bean
public FilterRegistrationBean<MyFilter> myFilterRegistationBean() {
FilterRegistationBean frb = new FilterRegistrationBean(myFilter());
frb.setEnabled(false);
return frb;
}
Finally remove the #Component from your MyFilter as you don't need it and it would create an additional instance. All prior changes (like the ApplicationInitializer etc. you can remove.
NOTE: As you are using Spring Security and somehow use this for authentication, instead of extending OncePerRequestFilter I suggest you extend the Spring Security AbstractAuthenticationProcessingFilter which integrates better with Spring Security (like fireing events for authentication, logging etc.).
I see you are creating a new instance of MyFilter instead of using the one managed by Spring with #Component(value = "MyFilter")
httpSecurity.addFilterBefore(new MyFilter(), UsernamePasswordAuthenticationFilter.class);
Hence you will hit a NPE since jdbcTemplate is null. You can inject the instance managed be Spring instead of creating a new one.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("MyFilter")
private MyFilter myFilter;
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests().anyRequest().authenticated();
httpSecurity.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
}
}
You should use this:
Through this class you can get different Spring Boot Beans in a non Bean class.
#Component
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext ctx;
#Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}
Then after creating it, get your bean this way:
ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext();
// Here you get your dependency
ARequiredClass dependency = appCtx.getBean(ARequiredClass.class);

Losing application context in #controller when adding #Around advice and exception is thrown

At first I code a RestController with ExceptionHandlers and everything works well. When I added an advice that wrap my #RequestMapping (with #Around) it broke my ExceptionHandler. When exception is thrown. E.g., TypeMisMatchException, All of a sudden, my controller lost its autowired beans (all of them are null).
I added a check in #PostConstruct and saw that my controller actually wires the beans.
MyRestContoller:
#RestController
#ControllerAdvice
public class MyRestController implements MyRestControllerInterface<Throwable> {
#Autowired private ApplicationContext applicationContext;
#Autowired private FirstBean firstBean;
#Autowired private SecondBean secondBean;
#PostConstruct
private void init() {
//just to print that beans are auto wired properly
//All beans are ok
}
#RequestMapping(value=“/”, method=RequestMethod.POST)
public ResponseEntity<String> postData(#SuppressWarnings("unused") #PathVariable ValidVersion version, #RequestBody DataRequest dataRequest) throws Throwable {
//stuff
return new ResponseEntity<>(newObj, HttpStatus.CREATED);
}
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler(Throwable.class)
private ErrorInfo handleBadRequest(HttpServletRequest req, Exception e) {
log.error("Error serving URL '" + req.getRequestURL()+ "': ", e);
//do something with firstBean
//but if thrown with configured advice the firstBean is null,
//and secondBean and applicationContext...
//
return new ErrorInfo(ErrorCodes.InternalServerError, req.getRequestURL().toString(), null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
My Aspect:
#Service
#Aspect
public class SomeAspect {
#Autowired private GraphiteBeanReporter graphiteBeanReporter;
#Pointcut("within(#org.springframework.web.bind.annotation.RestController *)")
public void restController() {}
#Pointcut("execution(* com.sample.MyRestController.*(..))")
public void methodPointcut() {}
#Around("restController() && methodPointcut()")
public Object whatToDoAround(ProceedingJoinPoint joinPoint) throws Throwable {
String metricName = joinPoint.getSignature().getName();
log.trace("inside the aspect of method '{}', metricName);
Context time = graphiteBeanReporter.initAndStartTimerMetic(metricName);
try {
Object result = joinPoint.proceed();
return result;
} finally {
if (time != null)
time.stop();
}
}
Just to add more information
The MyRestController and SomeAspect beans are configured in MVCCOnfig.class
while other business logic beans (i.e. FirstBean, SecondBean and more) are configured in AppConfig.class
My Initializer:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public WebAppInitializer() {
// stuff
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class, AppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MVCConfig.class };
}
}
Edit
added the implementation of whatToDoAround advice. It's basically report metric ('timer') to Graphite server using autowired bean. As I mentioned, if no exception is thrown in the controller, the metric is reported as expected.
Update -
specifically, ValidVersion is an enum that represent my API valid versions. An Exception is thrown where in the url #PathVariable is set with unknown String (one that can't be converted to enum value). This exception doesn't trigger any of my advices. I even tried to use #AfterThrowing without any success.

Spring Security method level security with Java config + REST Authentification?

I'm trying to add an authentification to my RestController, but i can't find any good documentation or any sample with Java Configuration.
I tried this but it doesn't work (i can access to all request without login)
My controller is annotated with #PreAuthorize
#RestController
#RequestMapping("/api/hello")
public class HelloController {
#RequestMapping(value = "/say", method = RequestMethod.GET)
public String sayHello() {
return "hello";
}
#PreAuthorize("hasRole('ROLE_USER')")
#RequestMapping(value = "/say/user", method = RequestMethod.GET)
public String sayHelloWithUserProtection(){
return "Hello USER";
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/say/admin", method = RequestMethod.GET)
public String sayHelloWithAdminrProtection(){
return "Hello ADMIN";
}
}
SecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(basePackages = {"com.test.server.security"})
public class SecurityConfig {
#Autowired
public void configureAuthentification(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("admin").roles("USER","ADMIN");
}
#Configuration
public static class ApiWebConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.formLogin();
}
}
}
SecurityWebApplicationInitializer
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
How can i make it work?
And there is any good tutorial to make a REST token based (token which save session key and others custom values) authentification saved in database with JPA (or JDBC ?) with Java configuration ?
Drop the formLogin(). You need to maintain the mindset that REST is supposed to be stateless. Logging in with a form this way, is not purely REST.
You can create a fine masked filter with Spring security chains like this (randomly just added stuff to create a more complete. Spring Security works by filters, which means that you need to create an actual filter before it kicks in. Specifically you need to authorize requests before matching them to paths.
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/say/user/").hasRole("USER")
.antMatchers("/say/admin").hasRole("ADMIN")
.anyRequest().authenticated();
The code above should be self explaining. If not, I will try to elaborate on it.
As for token based login, this is a good idea, but you should not roll your own.
Spring has great Oauth support and getting started securing your REST API with it is awesome.
This tutorial explains it in great detail and should help you further in building better API's as well.
http://spring.io/guides/tutorials/bookmarks/
Also make sure you have a look at Fowler's writings on REST here
http://martinfowler.com/articles/richardsonMaturityModel.html
I forgot to put my WebApplicationInitialisation in the question.
My error was i put SecurityConfig in getRootConfigClasses() instead of getServletConfigClasses().
Now WebApplicationInitialisation looks like this and it work great !
public class WebApplicationInitialisation extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebMvcConfig.class, SecurityConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
}
}

Tomcat 7 and AbstractSecurityWebApplicationInitializer are not working together

I was following this article to try a basic http-auth without the use of a web.xml
I'm using Tomcat 7.0.41 and those are my dependencies on gradle:
ext.springVersion = "3.2.1.RELEASE"
compile "org.springframework:spring-jdbc:$springVersion",
"org.springframework:spring-context:$springVersion",
"org.springframework:spring-web:$springVersion",
"org.springframework:spring-webmvc:$springVersion",
"org.springframework.security:spring-security-core:3.2.0.M2",
"org.springframework.security:spring-security-web:3.2.0.M2",
"org.springframework.security:spring-security-config:3.2.0.M2",
According to the tutorial I defined the following
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeUrls().antMatchers("/").hasRole("USER")
.and().httpBasic();
}
}
then added that class to the initializer like this:
#Order(1)
public class ServletConfiguration extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfiguration.class };
// return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { AppConfiguration.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
// #Override
// protected Dynamic registerServletFilter(ServletContext servletContext,
// Filter filter) {
// Dynamic securityFilter = servletContext.addFilter(
// "springSecurityFilterChain", DelegatingFilterProxy.class);
// securityFilter.addMappingForUrlPatterns(
// EnumSet.allOf(DispatcherType.class), false, "/*");
// return securityFilter;
// }
}
and finally added a class to inizialize the springSecurityFilterChain:
#Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
#Override
protected void afterSpringSecurityFilterChain(ServletContext servletContext) {
System.out.println("afterSpringSecurityFilterChain");
super.afterSpringSecurityFilterChain(servletContext);
}
}
But I'm always getting this error:
DEBUG: org.springframework.jndi.JndiPropertySource - JNDI lookup for name [spring.liveBeansView.mbeanDomain] threw NamingException with message: Name [spring.liveBeansView.mbeanDomain] is not bound in this Context. Unable to find [spring.liveBeansView.mbeanDomain].. Returning null.
Jul 11, 2013 9:22:24 PM org.apache.catalina.core.StandardContext filterStart
SEVERE: Exception starting filter springSecurityFilterChain
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' is defined
I don't why though, because when I go debugging the server initialization, actually these two methods are called:
#Override
public final void onStartup(ServletContext servletContext)
throws ServletException {
if(enableHttpSessionEventPublisher()) {
servletContext.addListener(HttpSessionEventPublisher.class);
}
insertSpringSecurityFilterChain(servletContext);
afterSpringSecurityFilterChain(servletContext);
}
then
private void insertSpringSecurityFilterChain(ServletContext servletContext) {
String filterName = "springSecurityFilterChain";
DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(filterName);
String contextAttribute = getWebApplicationContextAttribute();
if(contextAttribute != null) {
springSecurityFilterChain.setContextAttribute(contextAttribute);
}
registerFilter(servletContext, true, filterName, springSecurityFilterChain);
}
So actually the filter gets created. But then it gets lost somewhere.
I tried to play with #Order, but that was doing nothing so I tried to register springSecurityFilterChain using the registerServletFilter method but I'm not getting any http-auth request authentication.
And also SecurityConfiguration doens't even get loaded.
SecurityInitializer creates the DelegatingFilterProxy which is used to look up a bean by the name of springSecurityFilterChain. The springSecurityFilterChain is created using #EnableWebSecurity. The problem is that you are missing the #Configuration annotation (without it the Root ApplicationContext is not even going to try to load the SecurityConfiguration). Specifically you want to do the following:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
A few additional things to point out:
You do not need to use the #Order because you are not adding any other Filters
The only URL you have secured is the context root (i.e. /).
You will want to be aware of a bug with httpBasic() that is discussed on need spring security java config example showing basic auth only
UPDATE: I should have also pointed out that I have already logged SPR-10660 to support #Enable* annotations without having #Configuration on them. After that is resolved, your issue would magically go away.

Categories