2011-12-27 2 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); 
        } 
    } 
    
  • 구성 같은 확장하여 사용자 정의의 EntryPoint를 만듭니다

    1. 는 ChannelProcessingFilter를 확장하여 사용자 정의 ChannelProcessingFilter 만들기 applicationContext-security.xml 파일에 있습니다. 나는 (필요없는 부분을 제거하는 단계를 포함한다. 필요한 경우 다른 부분이 알려 않음) 참조의 전체 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> 
      

    을 내 바람둥이 :

     
    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) 
    

    나는 또한 다른 필터들을 오버라이드했으며 그것들에 대해서 불평하지 않는다. 이 응용 프로그램은 이전에 완벽하게 정상적으로 실행되었습니다. 우리는이 추가 요구 사항을 가지고 있었기 때문에 새 필터를 추가하고 이러한 오류가 발생했습니다.

    제가 시도한 두 번째 방법은 스프링 3.0에서 필터가 자동으로 호출되기 때문에 XML에서 기본 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는 XML의 일부인 사용자 정의 값을 사용하여 기본값과 두 번 초기화되어 두 번 초기화됩니다. 규칙을 적용 할 때 기본값을 사용하는 규칙 만 사용합니다. 어딘가에서 아주 작은 링크가 누락 된 것처럼 보입니다. –

    답변

    2

    솔루션 : HTTP뿐만 아니라 myChannelProcessingFilter 보안의 액세스 인수를 다루는 (I 오버라이드 (override)했던 일) :

    문제는 우리가 보안을 모두 가질 수 없다는 것입니다 : 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 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 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 { 
        @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; 
        } 
    } 
    
    관련 문제