I am using Spring Boot 2.1.4.Release, Primefaces 6.2, Java 8.
I am using Spring Security for signing in via the page "login.xhtml". All the pages of my application include a menu component(Menu.xhtml). Menu component has the functions such as logout, locale settings etc. In other words, the locale of the pages are set from the Menu.xhtml.
The problem is, when the locale settings are changed in the login page, a "POST /login.xhtml" request is made, which ends with UsernamePasswordAuthenticationFilter doing an authentication check. However, I want to stay on the login page after updating the locale settings. What I wonder is how to avoid this post request.
Here is the related parts of the WebSecurity implementation:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailServiceImp userDetailsService;
@Autowired
public SecurityConfig(UserDetailServiceImp userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// require all requests to be authenticated except for the resources
http.authorizeRequests()
.antMatchers("/user/**").hasAuthority(MediaJuryConstants.USER_ROLE)
.antMatchers("/javax.faces.resource/**").permitAll()
.antMatchers("/favicon.ico").permitAll()
.anyRequest().authenticated()
.and().authorizeRequests().antMatchers("/").anonymous();
// login
http.formLogin()
.loginPage("/login" + MediaJuryConstants.PREFIX)
.usernameParameter("loginForm:username")
.passwordParameter("loginForm:password")
.successHandler(myAuthenticationSuccessHandler())
.permitAll()
.failureUrl("/error" + MediaJuryConstants.PREFIX);
// logout
http.logout().logoutSuccessUrl("/login" + MediaJuryConstants.PREFIX);
http.csrf().disable();
}
...
}
Here is the p:selectOneMenu implementation used for selecting the locale in the Menu.xhtml:
<h:body>
<h:form id="langForm" styleClass="language-form">
<p:selectOneMenu value="#{language.localeCode}" valueChangeListener="#{languageChangeController.valueChanged}"
onchange="submit()">
<f:selectItems value="#{language.languageUtils.locales}" var="locale"
itemValue="#{locale}" itemLabel="#{msg['layout.'.concat(locale)]}"/>
</p:selectOneMenu>
</h:form>
</h:body>
I have a custom layout.xhtml that sets the global component for all pages. Here is the part where the Menu.xhtml is placed:
<h:body>
<div class="wrap">
<div class="header">
<div class="content ui-widget-content">
<ui:include src="tiles/Menu.xhtml" />
</div>
</div>
</div>
</h:body>
I am not providing the login.xhtml or the LanguageController since I do not think it is useful. But if demanded I can.
Here is my log. In this case the username and password fields are empty:
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.FilterChainProxy - /login.xhtml at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.FilterChainProxy - /login.xhtml at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@797fe12e. A new one will be created.
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.FilterChainProxy - /login.xhtml at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.FilterChainProxy - /login.xhtml at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET]
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'POST /login.xhtml' doesn't match 'GET /logout'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST]
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login.xhtml'; against '/logout'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT]
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'POST /login.xhtml' doesn't match 'PUT /logout'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE]
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'POST /login.xhtml' doesn't match 'DELETE /logout'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.OrRequestMatcher - No matches found
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.FilterChainProxy - /login.xhtml at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login.xhtml'; against '/login.xhtml'
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Request is to process authentication
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.s.a.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
17:49:34.368 [http-nio-8080-exec-10] DEBUG o.s.o.j.JpaTransactionManager - Creating new transaction with name [net.comerge.mediajury.service.UserService.findByEmail]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
17:49:34.369 [http-nio-8080-exec-10] DEBUG o.s.o.j.JpaTransactionManager - Opened new EntityManager [SessionImpl(1298794356<open>)] for JPA transaction
17:49:34.369 [http-nio-8080-exec-10] DEBUG o.h.e.t.i.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
17:49:34.369 [http-nio-8080-exec-10] DEBUG o.h.e.t.i.TransactionImpl - begin
17:49:34.369 [http-nio-8080-exec-10] DEBUG o.s.o.j.JpaTransactionManager - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@773cf27f]
17:49:34.369 [http-nio-8080-exec-10] DEBUG o.h.q.c.i.CriteriaQueryImpl - Rendered criteria query -> select generatedAlias0 from User as generatedAlias0 where generatedAlias0.email=:param0
17:49:34.370 [http-nio-8080-exec-10] DEBUG o.h.SQL - select user0_.id as id1_11_, user0_.email as email2_11_, user0_.locale as locale3_11_, user0_.password as password4_11_, user0_.state as state5_11_, user0_.verification_key as verifica6_11_ from user user0_ where user0_.email=?
17:49:34.371 [http-nio-8080-exec-10] DEBUG o.s.o.j.JpaTransactionManager - Initiating transaction commit
17:49:34.371 [http-nio-8080-exec-10] DEBUG o.s.o.j.JpaTransactionManager - Committing JPA transaction on EntityManager [SessionImpl(1298794356<open>)]
17:49:34.371 [http-nio-8080-exec-10] DEBUG o.h.e.t.i.TransactionImpl - committing
17:49:34.371 [http-nio-8080-exec-10] DEBUG o.s.o.j.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(1298794356<open>)] after transaction
17:49:34.371 [http-nio-8080-exec-10] DEBUG o.s.s.a.d.DaoAuthenticationProvider - User '' not found
17:49:34.371 [http-nio-8080-exec-10] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
org.springframework.security.authentication.BadCredentialsException: Bad credentials
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:151)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:200)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
17:49:34.372 [http-nio-8080-exec-10] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Updated SecurityContextHolder to contain null Authentication
17:49:34.372 [http-nio-8080-exec-10] DEBUG o.s.s.w.a.UsernamePasswordAuthenticationFilter - Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@1599e2f9
17:49:34.372 [http-nio-8080-exec-10] DEBUG o.s.s.w.a.SimpleUrlAuthenticationFailureHandler - Redirecting to /error.xhtml
17:49:34.372 [http-nio-8080-exec-10] DEBUG o.s.s.w.DefaultRedirectStrategy - Redirecting to '/error.xhtml'
When the language is changed using the selectOneMenu in login page, a POST /login.xhtml request is made which is caught by Spring Security and interpreted as a login attempt. I wanted to ask, where this POST request is made exactly and if there is a way to avoid POST method and do a GET method. FYI, the code does not enter valueChangeListener in the described case.
I would really appreciate some advice. Thank you in advance!