2011-12-27 16 views
9

チャネルプロセッサのデフォルトの動作は、sendRedirect(302コードで一時的にリダイレクト)です。 302リダイレクトの代わりに永続的な(301)リダイレクトが行われるように、この動作を変更する必要があります。私が実行しようとしました次:Spring Security 3.0.5でChannelProcessingFilterをオーバーライドします。

public class MyChannelProcessingFilter extends ChannelProcessingFilter{ 
    //No implementation, I needed this to just make sure that a custom filter is created and I can configure it as a custom filter in the xml file. 
} 
  • AbstractRetryEntryPoint

    public class RetryWithHttpsEntryPoint extends org.springframework.security.web.access.channel.AbstractRetryEntryPoint { 
        private PortResolver portResolver = new PortResolverImpl(); 
        private final String scheme ="https://"; 
        /** The standard port for the scheme (80 for http, 443 for https) */ 
        private final int standardPort = 443; 
    
        public RetryWithHttpsEntryPoint() { 
         super("https://", 443); 
        } 
    
        @Override 
        public void commence(HttpServletRequest request, HttpServletResponse res) throws IOException, ServletException { 
         String queryString = request.getQueryString(); 
         String redirectUrl = request.getRequestURI() + ((queryString == null) ? "" : ("?" + queryString)); 
    
         Integer currentPort = new Integer(portResolver.getServerPort(request)); 
         Integer redirectPort = getMappedPort(currentPort); 
    
         if (redirectPort != null) { 
          boolean includePort = redirectPort.intValue() != standardPort; 
    
          redirectUrl = scheme + request.getServerName() + ((includePort) ? (":" + redirectPort) : "") + redirectUrl; 
         } 
    
         if (logger.isDebugEnabled()) { 
          logger.debug("Redirecting to: " + redirectUrl); 
         } 
    
         res.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 
         res.setHeader("Location", redirectUrl); 
         res.setHeader("Connection", "close"); 
        } 
    
        protected Integer getMappedPort(Integer mapFromPort) { 
         return getPortMapper().lookupHttpsPort(mapFromPort); 
        } 
    } 
    
  • の設定と同じに拡張してカスタムエントリーポイントを作成します。

    1. はChannelProcessingFilterを拡張してカスタムChannelProcessingFilterを作成します。 applicationContext-security.xmlファイルに格納されます。私は私が実行しようとすると、私は次のエラーを取得しています

      (あなたが他の部品が必要な場合は私に知らせてください。必要のない部分を削除)
      <?xml version="1.0" encoding="UTF-8"?> 
      
      <beans xmlns="http://www.springframework.org/schema/beans" 
          xmlns:security="http://www.springframework.org/schema/security" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xmlns:util="http://www.springframework.org/schema/util" 
          xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
            http://www.springframework.org/schema/security 
            http://www.springframework.org/schema/security/spring-security-3.0.3.xsd 
            http://www.springframework.org/schema/util 
            http://www.springframework.org/schema/util/spring-util.xsd"> 
      
          <security:http auto-config="false" 
            entry-point-ref="authenticationProcessingFilterEntryPoint" 
            access-decision-manager-ref="accessDecisionManager" > 
           <security:intercept-url pattern="/activ8/protectedCheckEligibility.html**" access="user" requires-channel="https"/> 
           <security:intercept-url pattern="/siteMap.html" access="ROLE_ANONYMOUS,user,admin" requires-channel="http"/> 
           <security:intercept-url pattern="/privacyPolicy.html" access="ROLE_ANONYMOUS,user,admin" requires-channel="http"/> 
           <!-- other urls configured over here --> 
           <security:intercept-url pattern="/*.jsp" access="ROLE_ANONYMOUS,admin,user" requires-channel="https"/> 
           <security:intercept-url pattern="/**/*.html**" access="ROLE_ANONYMOUS,user,admin" requires-channel="https"/> 
           <security:intercept-url pattern="/fb_activities.html**" access="parent" />  
      
           <security:remember-me key="appfuseRocks" /> 
           <security:custom-filter position="SWITCH_USER_FILTER" ref="careSwitchUserProcessingFilter"/> 
           <security:custom-filter position="FORM_LOGIN_FILTER" ref="myCustomAuthenticationProcessingFilter"/> 
           <!-- configured the custom channel filter over here --> 
           <security:custom-filter position="CHANNEL_FILTER" ref="myChannelProcessingFilter"/> 
          </security:http> 
      
          <bean id="myChannelProcessingFilter" class="com.my.webapp.filter.myChannelProcessingFilter"> 
           <property name="channelDecisionManager" ref="channelDecisionManager" /> 
           <property name="securityMetadataSource"> 
            <security:filter-security-metadata-source path-type="ant"> 
             <security:intercept-url pattern="/**" access="REQUIRES_INSECURE_CHANNEL" /> 
            </security:filter-security-metadata-source> 
           </property> 
          </bean> 
      
          <bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl"> 
           <property name="channelProcessors"> 
            <list> 
             <ref bean="secureChannelProcessor"/> 
            </list> 
           </property> 
          </bean> 
      
          <bean id="secureChannelProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor"> 
           <property name="entryPoint" ref="secureChannelEntryPoint"/> 
           <!-- <property name="portMapper" ref="portMapper" /> --> 
           <property name="secureKeyword" value="REQUIRES_SECURE_CHANNEL"/> 
          </bean> 
      
          <bean id="secureChannelEntryPoint" class="com.my.webapp.filter.RetryWithHttpsEntryPoint"/> 
      
          <!-- lot of other configuratons... removed --> 
      
      </beans> 
      

    をご参考のための完全なxmlファイルを入れています私の部屋:

     
    ERROR 2011-12-26 21:13:21,569 [ina].[localhost].[/]]: Exception sending context initialized event to listener instance of class com.kajeet.webapp.listener.StartupListener 
    org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Filter beans '' and 'Root bean: class [org.springframework.security.web.access.channel.ChannelProcessingFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null' have the same 'order' value. When using custom filters, please make sure the positions do not conflict with default filters. Alternatively you can disable the default filters by removing the corresponding child elements from and avoiding the use of . 
        Offending resource: ServletContext resource [/WEB-INF/applicationContext-security.xml] 
        at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68) 
        at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85) 
        at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:72) 
        at org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.checkFilterChainOrder(HttpSecurityBeanDefinitionParser.java:196) 
        at org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.parse(HttpSecurityBeanDefinitionParser.java:132) 
        at org.springframework.security.config.SecurityNamespaceHandler.parse(SecurityNamespaceHandler.java:86) 
        at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1335) 
        at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1325) 
        at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135) 
        at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93) 
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493) 
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390) 
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334) 
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302) 
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143) 
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178) 
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149) 
        at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124) 
        at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:93) 
        at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130) 
        at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467) 
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:397) 
        at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276) 
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197) 
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) 
        at com.kajeet.webapp.listener.StartupListener.contextInitialized(StartupListener.java:51) 
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3764) 
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:4216) 
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:760) 
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:740) 
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:544) 
        at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920) 
        at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883) 
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492) 
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138) 
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311) 
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:120) 
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1022) 
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:736) 
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014) 
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) 
        at org.apache.catalina.core.StandardService.start(StandardService.java:448) 
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:700) 
        at org.apache.catalina.startup.Catalina.start(Catalina.java:552) 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
        at java.lang.reflect.Method.invoke(Method.java:597) 
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:295) 
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:433) 
    

    私は他のフィルタもオーバーライドしていますが、それらについては不平を言っていません。このアプリケーションは前に完全に正常に動作していました。この追加要件があり、新しいフィルタを追加してこのようなエラーに遭遇しました。

    私が試した2番目のアプローチは、Spring 3.0ではフィルタが自動的に呼び出されるため、XMLファイルでそれらを構成でき、Springが自動的にそれらをロードするので、デフォルトのChannelProcessingFilterをXMLで構成しています。していませんでした:

    <?xml version="1.0" encoding="UTF-8"?> 
    
        <beans xmlns="http://www.springframework.org/schema/beans" 
         xmlns:security="http://www.springframework.org/schema/security" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns:util="http://www.springframework.org/schema/util" 
         xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
           http://www.springframework.org/schema/security 
           http://www.springframework.org/schema/security/spring-security-3.0.3.xsd 
           http://www.springframework.org/schema/util 
           http://www.springframework.org/schema/util/spring-util.xsd"> 
    
         <security:http auto-config="false" 
           entry-point-ref="authenticationProcessingFilterEntryPoint" 
           access-decision-manager-ref="accessDecisionManager" > 
          <security:intercept-url pattern="/activ8/protectedCheckEligibility.html**" access="user" requires-channel="https"/> 
          <security:intercept-url pattern="/siteMap.html" access="ROLE_ANONYMOUS,user,admin" requires-channel="http"/> 
          <security:intercept-url pattern="/privacyPolicy.html" access="ROLE_ANONYMOUS,user,admin" requires-channel="http"/> 
          <!-- other urls configured over here --> 
          <security:intercept-url pattern="/*.jsp" access="ROLE_ANONYMOUS,admin,user" requires-channel="https"/> 
          <security:intercept-url pattern="/**/*.html**" access="ROLE_ANONYMOUS,user,admin" requires-channel="https"/> 
          <security:intercept-url pattern="/fb_activities.html**" access="parent" />  
    
          <security:remember-me key="appfuseRocks" /> 
          <security:custom-filter position="SWITCH_USER_FILTER" ref="careSwitchUserProcessingFilter"/> 
          <security:custom-filter position="FORM_LOGIN_FILTER" ref="myCustomAuthenticationProcessingFilter"/> 
         </security:http> 
    
         <bean id="channelDecisionManager" class="org.springframework.security.securechannel.ChannelDecisionManagerImpl"> 
          <property name="channelProcessors"> 
           <list> 
            <ref bean="secureChannelProcessor"/> 
            <ref bean="insecureChannelProcessor"/> 
           </list> 
          </property> 
         </bean> 
    
         <bean id="secureChannelProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor"/> 
         <bean id="insecureChannelProcessor" class="org.springframework.security.web.access.channel.InsecureChannelProcessor"/> 
    
         <!-- lot of other configuratons... removed --> 
    
        </beans> 
    

    ご協力いただけると幸いです。私は春のプロではありませんが、私はいくつかの作業を行っています。ポインタまたは2つが間違いなくこれを解決するのに役立つかもしれません。事前にありがとう

  • +0

    、私はこれがChannelProcessingFilterの拡張を必要としないことを知りました。私が見つけた問題は、SecureChannelProce ssorはデフォルト値で2回、XMLの一部であるカスタム値で2回初期化されます。ルールを適用するときは、デフォルト値を使用するだけです。私はどこかに非常に小さなリンクがないようです。 –

    答えて

    2

    ソリューション:セキュリティのアクセス引数に対処するために、HTTPと同様にmyChannelProcessingFilter(私は上書きしていた1):

    は、問題は、我々はセキュリティの両方を持つことができないということです。 intercept-url、私はhttpタグを削除し、myChannelProcessingFilterでアクセスするものを追加しました。それを解決したXMLは次のとおりです

    <?xml version="1.0" encoding="UTF-8"?> 
    
    <beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:security="http://www.springframework.org/schema/security" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:util="http://www.springframework.org/schema/util" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
          http://www.springframework.org/schema/security 
          http://www.springframework.org/schema/security/spring-security-3.0.3.xsd 
          http://www.springframework.org/schema/util 
          http://www.springframework.org/schema/util/spring-util.xsd"> 
    
        <!-- 
         The http element responsible for creating a FilterChainProxy and the filter beans which it uses. 
         Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined. 
        --> 
        <security:http auto-config="false" 
          entry-point-ref="authenticationProcessingFilterEntryPoint" 
          access-decision-manager-ref="accessDecisionManager" > 
    
         <security:custom-filter position="CHANNEL_FILTER" ref="channelProcessingFilter"/> 
    
         <security:intercept-url pattern="/*.html*" access="ROLE_ANONYMOUS,admin,user" /> 
         <security:intercept-url pattern="/*.jsp" access="ROLE_ANONYMOUS,admin,user" /> 
         <security:intercept-url pattern="/**/*.html**" access="ROLE_ANONYMOUS,user,admin" /> 
    
    
        </security:http> 
    
        <bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter"> 
         <property name="channelDecisionManager" ref="channelDecisionManager"/> 
         <property name="securityMetadataSource"> 
         <security:filter-security-metadata-source path-type="ant"> 
          <security:intercept-url pattern="/*.jsp**" access="REQUIRES_SECURE_CHANNEL" /> 
          <security:intercept-url pattern="/**/*.html**" access="REQUIRES_SECURE_CHANNEL" /> 
         </security:filter-security-metadata-source> 
         </property> 
        </bean> 
    
        <bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl"> 
         <property name="channelProcessors"> 
          <list> 
           <ref bean="secureProcessor"/> 
           <ref bean="insecureProcessor"/> 
          </list> 
         </property> 
        </bean> 
    
        <bean id="secureProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor" > 
         <property name="entryPoint" ref="retryWithHttps"/> 
        </bean> 
    
        <bean id="insecureProcessor" class="org.springframework.security.web.access.channel.InsecureChannelProcessor"> 
         <property name="entryPoint" ref="retryWithHttp"/> 
        </bean> 
    
        <bean id="retryWithHttps" class="com.my.webapp.filter.RetryWithHttpsEntryPoint" /> 
        <bean id="retryWithHttp" class="com.my.webapp.filter.RetryWithHttpEntryPoint" /> 
    
    </beans> 
    
    0

    コードと複雑さがはるかに少ない同じ方法を実現する別の方法が見つかりました。 BeanPostProcessorを使用してSecureChannelProcessorInsecureChannelProcessorを取得し、独自のエントリポイントを設定するだけです。そうすれば、他のすべてのものに対してもデフォルトを使用することができます。

    BeanPostProcessor:

    @Component 
    public class PermanentRedirectStrategy implements RedirectStrategy { 
        private boolean contextRelative; 
    
        @Override 
        public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { 
         response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 
         response.setHeader("Location", response.encodeRedirectURL(calculateRedirectUrl(request.getContextPath(), url))); 
        } 
    
        /** 
        * Unfortunately DefaultRedirectStrategy.calculateRedirectUrl is private 
        * If this weren't the case, we could extend this class from DefaultRedirectStrategy 
        * to use its method directly without copying it 
        */ 
        private String calculateRedirectUrl(String contextPath, String url) { 
         if (!UrlUtils.isAbsoluteUrl(url)) { 
          if (contextRelative) { 
           return url; 
          } else { 
           return contextPath + url; 
          } 
         } 
    
         // Full URL, including http(s):// 
    
         if (!contextRelative) { 
          return url; 
         } 
    
         // Calculate the relative URL from the fully qualified URL, minus the last 
         // occurence of the scheme and base context 
         url = url.substring(url.lastIndexOf("://") + 3); // strip off scheme 
         url = url.substring(url.indexOf(contextPath) + contextPath.length()); 
    
         if (url.length() > 1 && url.charAt(0) == '/') { 
          url = url.substring(1); 
         } 
    
         return url; 
        } 
    } 
    

    し、既存のエントリ・ポイントに設定する::

    @Component 
    public class ChannelProcessorsPostProcessor implements BeanPostProcessor { 
    
        @Override 
        public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException { 
    
         if (bean instanceof SecureChannelProcessor) ((SecureChannelProcessor)bean).setEntryPoint(new MyEntryRetryPoint("https://", 443)); 
         else if (bean instanceof InsecureChannelProcessor) ((InsecureChannelProcessor)bean).setEntryPoint(new MyEntryRetryPoint("http://", 80)); 
    
         return bean; 
        } 
    
        @Override 
        public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException { 
    
         return bean; 
        } 
    } 
    
    0

    私はそれがリダイレクト戦略を書く方が良いと思い、今後の検討課題で

    @Component 
    public class ChannelProcessorsPostProcessor implements BeanPostProcessor { 
        @Autowired 
        private RedirectStrategy permanentRedirectStrategy; 
    
        @Override 
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
         ChannelEntryPoint entryPoint = null; 
    
         if (bean instanceof SecureChannelProcessor) { 
          entryPoint = ((SecureChannelProcessor) bean).getEntryPoint(); 
         } else if (bean instanceof InsecureChannelProcessor) { 
          entryPoint = ((InsecureChannelProcessor) bean).getEntryPoint(); 
         } 
    
         if (entryPoint != null && AbstractRetryEntryPoint.class.isAssignableFrom(entryPoint.getClass())) { 
          ((AbstractRetryEntryPoint) entryPoint).setRedirectStrategy(permanentRedirectStrategy); 
         } 
    
         return bean; 
        } 
    
        @Override 
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
         return bean; 
        } 
    }