2010-09-30 15 views
8

Je souhaite contourner le formulaire de connexion pour une application Spring webflow (Spring 2.0.5) sous certains scénarios (le formulaire de connexion est donc présenté pour les utilisateurs normaux mais lorsque l'URL est similaire à http://server.com/myspringapp/fakelogin?username=FakeUser&password=FakePassword alors l'utilisateur ne devrait pas être présenté le formulaire de connexion, mais juste authentifié en interne sur la base des paramètres de la demande, puis pris à la page sécurisée). Donc je ne veux pas de pré-authentification, plutôt une authentification transparente à des occasions spéciales (quand l'URL est comme mentionné ci-dessus). J'ai vu des discussions telles que http://forum.springsource.org/showthread.php?t=59108 mais pas où une solution est mentionnée. J'ai essayé d'implémenter le AuthenticationProcessingFilter mais je ne sais pas trop comment implémenter la méthode requiresAuthentication().Spring Security: Ignorer le formulaire de connexion

Ce qui suit est mon XML actuel de sécurité:

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

suivant est ma classe de filtre:

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

} 

Je suis en mesure d'authentifier en utilisant les paramètres de la requête fournis et l'objet d'authentification est créé avec succès. C'est une fois que le filtre se poursuit que j'obtiens l'exception:

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 

Pouvez-vous m'aider avec la raison pour laquelle je reçois cette erreur? Est-ce que j'utilise le bon type de filtre personnalisé? Apprécier ton aide.

Répondre

6

J'ai fait quelque chose de similaire avec Spring Security 3 et je pense que cela devrait aussi être possible avec les anciennes versions. J'ai modifié mon code, donc cela correspond à votre situation. Vous devrez peut-être travailler sur certains détails, mais cela devrait vous donner l'idée de base.

Vous pouvez gérer à l'aide d'un filtre:

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

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

Dans votre spring.xml:

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

Une autre option serait de permettre à tous les utilisateurs d'accéder à fakeLogin

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

et de mettre l'authentification dans le contexte de sécurité dans une action de flux Web.

+1

Vous pouvez également jeter un coup d'œil au filtre de pré-authentification de Spring. – martin