表单提交导致发布请求,该请求在登录页面中触发UsernamePasswordAuthenticationFilter

时间:2019-05-03 16:04:51

标签: spring-boot spring-mvc jsf spring-security

我正在使用Spring Boot 2.1.4.Release,Primefaces 6.2,Java 8。

我正在使用Spring Security通过“ login.xhtml”页面登录。 我的应用程序的所有页面都包含一个菜单组件(Menu.xhtml)。菜单组件具有注销,区域设置等功能。换句话说,页面的区域设置是通过Menu.xhtml设置的。

问题是,当在登录页面中更改语言环境设置时,会发出“ POST /login.xhtml”请求,该请求以UsernamePasswordAuthenticationFilter进行身份验证检查结束。但是,我想在更新语言环境设置后留在登录页面上。 我想知道的是如何避免发出此请求。

以下是WebSecurity实现的相关部分:



@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();
    }

...
}

这是用于在Menu.xhtml中选择语言环境的p:selectOneMenu实现:


<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>

我有一个自定义layout.xhtml,它为所有页面设置了全局组件。这是放置Menu.xhtml的部分:

<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>

我没有提供login.xhtml或LanguageController,因为我认为它没有用。但是如果需要的话我可以。

这是我的日志。在这种情况下,用户名和密码字段为空:

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'

使用登录页面中的selectOneMenu更改语言后, 发出POST /login.xhtml请求,该请求被Spring Security捕获并解释为登录尝试。 我想问一下,此POST请求是在哪里发出的,是否有避免POST方法并执行GET方法的方法。 仅供参考,在上述情况下,代码未输入valueChangeListener。

我真的很感谢一些建议。预先谢谢你!

1 个答案:

答案 0 :(得分:0)

我找不到基于xhtml的解决方案,但正如Kukeltje建议的那样,自定义实现UsernamePasswordAuthenticationFilter可以解决此问题。

表单组件如给定

  <h:form method="get" id="langForm" styleClass="language-form">
        <p:selectOneMenu value="#{languageController.localeCode}"  valueChangeListener="#{languageChangeController.valueChanged}"
        onchange="submit()">
            <f:selectItems value="#{languageController.languageUtils.locales}" var="locale"
                           itemValue="#{locale}" itemLabel="#{msg['layout.'.concat(locale)]}"/>
        </p:selectOneMenu>
    </h:form>

选择一个项目会导致当前页面的POST请求,我们正在login.xhtml:POST /login.xhtml上。该请求输入UsernamePasswordAuthenticationFilter的doFilter。如果requiresAuthentication方法返回true,则该方法进行身份验证检查。因此,重写此方法就足够了。

public class CustomUsernamePasswordFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        if (request.getParameter("langForm") != null) {
            return false;
        }
        return super.requiresAuthentication(request, response);
    }
}

langForm是xhtml中引入的表单的ID。