2010-09-30 4 views
8

Я хочу обойти форму входа для приложения Spring Webflow (Spring 2.0.5) в определенных сценариях (так что форма входа в систему представлена ​​для обычных пользователей, но когда URL-адрес похож на http://server.com/myspringapp/fakelogin?username=FakeUser&password=FakePassword, тогда пользователь не должна быть представлена ​​форма входа в систему, а просто проверена внутренне на основе параметров запроса, а затем отправлена ​​на защищенную страницу).Spring Security: Bypass login form

Так что я не хочу Preauthenticastion, а не прозрачную проверку подлинности при особых случаях (когда URL-адрес указан выше). Я видел такие темы, как http://forum.springsource.org/showthread.php?t=59108, но не там, где упоминается решение. Я попытался реализовать AuthenticationProcessingFilter, но не слишком уверен, как реализовать метод requireAuthentication().

Ниже мой текущий XML безопасности:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:security="http://www.springframework.org/schema/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
         http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd"> 

    <bean id="customAuthenticationProvider" class="com.myco.jsf.spring.security.MyAuthenticationProvider"> 
     <security:custom-authentication-provider/> 
     <constructor-arg> 
      <ref bean="webSessionFactory"/> 
     </constructor-arg> 
     <constructor-arg> 
      <ref bean="authenticationBridge"/> 
     </constructor-arg> 
    </bean> 

    <bean id="myEntryPoint" class="com.myco.web.filter.CustomAuthenticationEntryPoint"> 
     <property name="loginFormUrl" value="/spring/login" /> 
    </bean> 

    <bean id="myProcessingFilter" class="com.myco.web.filter.CustomAuthenticationProcessingFilter"> 
     <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" /> 
     <property name="defaultTargetUrl" value="/spring/secure" /> 
     <property name="authenticationFailureUrl" value="/spring/login" /> 
     <property name="alwaysUseDefaultTargetUrl" value="false" /> 
     <property name="filterProcessesUrl" value="/spring/j_spring_security_check" />  
     <property name="authenticationManager" ref="authenticationManager" />    
     <!--    
     <property name="allowSessionCreation" value="true" />     
     --> 
    </bean>  

    <security:authentication-manager alias="authenticationManager"/> 

     <security:http auto-config="false" access-denied-page="/spring/notpermitted" entry-point-ref="myEntryPoint">  
     <security:anonymous/> 
     <!--  
     <security:form-login login-page="/spring/login" login-processing-url="/spring/j_spring_security_check" default-target-url="/spring/secure" 
      always-use-default-target="false" authentication-failure-url="/spring/login" /> 
     --> 
     <security:logout logout-url="/spring/j_spring_security_logout" logout-success-url="/spring/pages/logout" /> 
     </security:http> 

</beans> 

Ниже мой класс фильтра:

public class CustomAuthenticationProcessingFilter extends 
     AuthenticationProcessingFilter { 

    @Override 
    protected void successfulAuthentication(HttpServletRequest request, 
      HttpServletResponse response, Authentication authResult) 
      throws IOException, ServletException { 
     super.successfulAuthentication(request, response, authResult); 

     System.out.println("==successful login=="); 
    } 

    @Override 
    protected void unsuccessfulAuthentication(HttpServletRequest request, 
      HttpServletResponse response, AuthenticationException failed) 
      throws IOException, ServletException { 
     super.unsuccessfulAuthentication(request, response, failed); 

     System.out.println("==failed login=="); 
    } 

    @Override 
    protected boolean requiresAuthentication(HttpServletRequest request, 
      HttpServletResponse response) { 
     boolean retVal = false; 
     String username = request.getParameter("j_username"); 
     String password = request.getParameter("j_password"); 

     if (username != null && password != null) { 
      Authentication authResult = null; 
      try { 
       authResult = attemptAuthentication(request);     
       if (authResult == null) { 
        retVal = false; 
       } 

      } catch (AuthenticationException failed) { 
       try { 
        unsuccessfulAuthentication(request, response, failed); 
       } catch (Exception e) { 
        retVal = false; 
       } 
       retVal = false; 
      } 

      try { 
       successfulAuthentication(request, response, authResult); 
      } catch (Exception e) { 
       retVal = false; 
      } 

      return false; 
     } else { 
      retVal = super.requiresAuthentication(request, response); 
     } 
     return retVal; 
    } 

} 

Я могу аутентификации с использованием параметров запроса, поставляемые и объект аутентификации создается успешно. После того, как фильтр продолжает действовать, я получаю исключение:

15:29:08,734 INFO [STDOUT] 53453 ERROR [http-127.0.0.1-8080-2]  org.ajax4jsf.webapp.BaseXMLFilter  - Exception in the filter chain 
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:659) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206) 
    at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290) 
    at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388) 
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at com.myco.jsf.filter.CharsetFilter.doFilter(CharsetFilter.java:38) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378) 
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109) 
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:278) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:173) 
    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182) 
    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104) 
    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157) 
    at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:393) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) 
    at java.lang.Thread.run(Thread.java:619) 
Caused by: java.lang.IllegalStateException 
    at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:407) 
    at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:108) 
    at org.springframework.security.context.HttpSessionContextIntegrationFilter$OnRedirectUpdateSessionResponseWrapper.sendError(HttpSessionContextIntegrationFilter.java:498) 
    at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:108) 
    at org.ajax4jsf.webapp.FilterServletResponseWrapper.sendError(FilterServletResponseWrapper.java:655) 
    at com.sun.facelets.FaceletViewHandler.handleFaceletNotFound(FaceletViewHandler.java:711) 
    at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:658) 
    at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100) 
    at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176) 
    at org.springframework.faces.mvc.JsfView.renderMergedOutputModel(JsfView.java:83) 
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250) 
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1060) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:798) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647) 
    ... 61 more 

Помогите мне с тем, почему я получаю эту ошибку? Я использую правильный тип настраиваемого фильтра? Ценю вашу помощь.

ответ

6

Я сделал что-то подобное с Spring Security 3, и я думаю, что это должно быть возможно и в старых версиях. Я изменил свой код, чтобы он соответствовал вашей ситуации. Возможно, вам придется разработать некоторые детали, но он должен предоставить вам основную идею.

Вы можете обрабатывать его с помощью фильтра:

public class MyAuthenticationFilter extends DelegatingFilterProxy 
{ 
    public void doFilter ... 
    { 
      String username = request.getParameter("username"); 
      String password = request.getParameter("password"); 

      // build authentication token for user 
      final Authentication auth = new UsernamePasswordAuthenticationToken(...); 
      auth.setAuthenticated(true); 

      // set authentication in context 
      SecurityContextHolder.getContext().setAuthentication(auth); 
    } 

В вашем web.xml:

<filter> 
    <filter-name>myAuthenticationFilter</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>myAuthenticationFilter</filter-name> 
    <url-pattern>/fakelogin*</url-pattern> 
</filter-mapping> 

В вашем spring.xml:

<bean id="myAuthenticationFilter" class=... /> 

Другим вариантом было бы разрешить всем пользователям получать доступ к fakeLogin

<intercept-url pattern="/fakelogin/**" access="permitAll" /> 

и установите аутентификацию в контексте безопасности в действии веб-потока.

+1

Вы также можете взглянуть на фильтр предварительной проверки Spring. – martin