2011-05-17 10 views
0

我希望有人能幫助我解決這個問題。我有一個使用Spring Security 3完美運行的Spring MVC應用程序(Spring 3),現在我們添加了對Flex的支持,並將BlazeDS添加到應用程序和Spring Integration(1.5.0 M2)中,所有這些應用程序都開始正常工作,直到我們想要集成通過Spring Security進行認證。 Flex應用程序是一個「迷你」UI,用作兩個用戶之間的P2P聊天(通過消息傳遞),它嵌入在Spring MVC應用程序的JSP頁面中,我們想要做的是確保(從Flex應用程序)用戶在顯示聊天界面之前已登錄。認證是從Spring MVC應用程序(一種Web表單)完成的,並且工作正常,但每次我們訪問保存Flex應用程序的Spring MVC頁面並從Flex進行遠程調用以獲取當前用戶詳細信息時,例外:Spring MVC頁面中的嵌入式Flex應用程序遠程調用彈出安全性錯誤

flex.messaging.security.SecurityException: An Authentication object was not found in the SecurityContext 

我們假設遠程請求(來自經過認證的會議上提出的)也會莫名其妙地被拾起,並承認和Flex客戶端並不需要重新驗證身份。這裏有什麼可能是錯的?這裏是我的春天的安全配置和我的Flex配置文件,以及在web.xml:

security.xml文件:

<bean id="springSecurityFilterChain" 
     class="org.springframework.security.web.FilterChainProxy"> 
     <sec:filter-chain-map path-type="ant">   
      <sec:filter-chain filters="none" pattern="/styles/**" /> 
      <sec:filter-chain filters="none" pattern="/js/**" /> 
      <sec:filter-chain filters="none" pattern="/images/**" /> 
      <sec:filter-chain 
       filters="securityContextPersistenceFilter, 
        logoutFilter, 
        usernamePasswordAuthenticationFilter, 
        anonymousAuthenticationFilter, 
        exceptionTranslationFilter, 
        menuLoaderRequestFilter, 
        filterSecurityInterceptor" 
       pattern="/web/**" /> 
      <sec:filter-chain 
       filters="securityContextPersistenceFilter, 
        usernamePasswordAuthenticationFilter, 
        exceptionTranslationFilter" 
       pattern="/do_login" />    
      <sec:filter-chain 
       filters="securityContextPersistenceFilter, 
        logoutFilter, 
        exceptionTranslationFilter" 
       pattern="/do_logout" /> 
     </sec:filter-chain-map> 
    </bean> 

    <bean id="securityContextPersistenceFilter" 
      class="org.springframework.security.web.context.SecurityContextPersistenceFilter" /> 

    <bean id="usernamePasswordAuthenticationFilter" 
     class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
     <property name="authenticationManager" 
       ref="authenticationManager" /> 
     <property name="filterProcessesUrl" value="/do_login"/> 
     <property name="authenticationFailureHandler"> 
      <ref bean="loginFailureHandler" /> 
     </property> 
     <property name="authenticationSuccessHandler"> 
      <ref bean="loginSuccessHandler" /> 
     </property> 
     <property name="usernameParameter" value="login_user" /> 
     <property name="passwordParameter" value="login_password" /> 
    </bean> 

    <bean id="loginFailureHandler" 
      class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler"> 
     <property name="defaultFailureUrl" value="/web/login?error=login.failure"/> 
     <property name="exceptionMappings"> 
      <map> 
       <entry> 
        <key> 
         <value>org.springframework.security.authentication.AuthenticationServiceException</value> 
        </key> 
        <value>/web/login?error=login.database.failure</value> 
       </entry> 
      </map> 
     </property> 
    </bean> 

    <bean id="loginSuccessHandler" 
      class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"> 
     <property name="defaultTargetUrl" value="/web/index"/> 
    </bean> 

    <bean id="anonymousAuthenticationFilter" 
     class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter"> 
     <property name="userAttribute" 
       value="anonymousUser,ROLE_ANONYMOUS" /> 
     <property name="key" value="AD17JFJ005P00Z7MK" /> 
    </bean> 

    <bean id="logoutFilter" 
     class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
     <!-- the post-logout destination --> 
     <constructor-arg value="/web/login?success=login.loggedout"/> 
     <constructor-arg> 
      <array> 
       <ref bean="logoutHandler" /> 
      </array> 
     </constructor-arg> 
     <property name="filterProcessesUrl" value="/do_logout"/> 
    </bean> 

    <bean id="logoutHandler" 
      class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" /> 

    <bean id="exceptionTranslationFilter" 
      class="org.springframework.security.web.access.ExceptionTranslationFilter"> 
     <property name="authenticationEntryPoint" 
      ref="mainEntryPoint"/> 
     <property name="accessDeniedHandler" ref="accessDeniedHandler"/> 
    </bean> 


    <bean id="mainEntryPoint" 
      class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">   
     <constructor-arg> 
      <map> 
       <entry> 
        <key> 
         <value>hasHeader('X-Requested-With', 'XMLHttpRequest')</value>      
        </key> 
        <ref bean="ajaxEntryPoint"/> 
       </entry> 
       <entry> 
        <key> 
         <value>hasHeader('Content-type', 'application/x-amf')</value> 
        </key> 
        <ref bean="flexEntryPoint" /> 
       </entry> 
      </map> 
     </constructor-arg>   
     <property name="defaultEntryPoint" ref="defaultEntryPoint" /> 
    </bean> 

    <bean id="entryPointTemplate" abstract="true"> 
     <property name="loginFormUrl" value="/web/login"/> 
    </bean> 

    <bean id="ajaxEntryPoint" parent="entryPointTemplate" 
      class="com.saes.support.security.AjaxAuthenticationEntryPoint" > 
    </bean> 

    <bean id="defaultEntryPoint" parent="entryPointTemplate" 
      class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">  
    </bean> 

    <bean id="flexEntryPoint" class="org.springframework.flex.security3.FlexAuthenticationEntryPoint"> 
    </bean> 

    <bean id="accessDeniedHandler" 
      class="com.saes.support.security.SAESAccessDeniedHandler"> 
     <property name="errorPage" 
       value="/web/errors/accessDenied"/> 
    </bean> 

    <bean id="filterSecurityInterceptor" 
     class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> 
     <property name="authenticationManager" 
       ref="authenticationManager"/> 
     <property name="accessDecisionManager" ref="decisionManager"/> 
     <property name="securityMetadataSource"> 
      <sec:filter-security-metadata-source> 
       <sec:intercept-url pattern="/web/profile/**" 
        access="ROLE_USER" /> 
       <sec:intercept-url pattern="/web/doctor/**" 
        access="ROLE_DOCTOR" /> 
      </sec:filter-security-metadata-source> 
     </property> 
    </bean> 

    <bean id="menuLoaderRequestFilter" 
       class="com.saes.security.menu.MenuPermissionsAdapterRequestFilter"> 
    </bean> 

    <bean id="decisionManager" 
     class="org.springframework.security.access.vote.AffirmativeBased"> 
     <property name="allowIfAllAbstainDecisions" value="false" /> 
     <property name="decisionVoters"> 
      <list> 
       <ref bean="roleVoter"/> 
       <ref bean="authenticatedVoter"/> 
      </list> 
     </property> 
    </bean> 

    <bean id="roleVoter" 
     class="org.springframework.security.access.vote.RoleVoter" /> 

    <bean id="authenticatedVoter" 
     class="org.springframework.security.access.vote.AuthenticatedVoter" /> 

    <bean id="daoAuthenticationProvider" 
     class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> 
     <property name="userDetailsService"> 
      <ref bean="userDetailsService" /> 
     </property> 
    </bean> 

    <bean id="anonymousAuthenticationProvider" 
     class="org.springframework.security.authentication.AnonymousAuthenticationProvider"> 
     <property name="key" value="AD17JFJ005P00Z7MK"/> 
    </bean> 

    <bean id="authenticationManager" 
     class="org.springframework.security.authentication.ProviderManager"> 
     <property name="providers"> 
      <list> 
       <ref bean="daoAuthenticationProvider" /> 
       <ref bean="anonymousAuthenticationProvider" /> 
      </list> 
     </property> 
    </bean> 

柔性servlet.xml中:

<flex:message-broker 
     services-config-path="/WEB-INF/config/flex/services-config.xml"> 

     <flex:secured authentication-manager="authenticationManager" 
     access-decision-manager="decisionManager"> 
      <flex:secured-endpoint-path pattern="**/messagebroker/*" access="ROLE_USER"/> 
     </flex:secured> 

    </flex:message-broker> 

的web.xml :

<context-param>  
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/config/spring/persistence.xml 
/WEB-INF/config/spring/security.xml 
/WEB-INF/config/spring/services.xml 
/WEB-INF/config/spring/facade.xml 
/WEB-INF/config/spring/validator.xml 
/WEB-INF/config/flex/flex-context.xml        
    </param-value> 
    </context-param> 
    <listener> 
    <listener-class> 
     org.springframework.web.context.ContextLoaderListener 
    </listener-class> 
    </listener> 
    <servlet>  
    <servlet-name>mainServlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>mainServlet</servlet-name> 
    <url-pattern>/web/*</url-pattern> 
    </servlet-mapping> 
    <servlet>  
    <servlet-name>flex</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>flex</servlet-name> 
    <url-pattern>/messagebroker/*</url-pattern> 
    </servlet-mapping>  
    <filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class> 
     org.springframework.web.filter.DelegatingFilterProxy 
    </filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    <welcome-file-list> 
    <welcome-file>index.html</welcome-file> 
    <welcome-file>index.jsp</welcome-file> 
    </welcome-file-list> 
    <error-page> 
    <error-code>500</error-code>  
    <location>/WEB-INF/jsp/errors/critical-error.jsp</location> 
    </error-page> 
    <error-page> 
    <error-code>404</error-code>  
    <location>/WEB-INF/jsp/errors/404.jsp</location> 
    </error-page> 

這裏是Flex代碼的相關部分:

<s:ChannelSet id="chatChannelSet"> 
     <s:StreamingAMFChannel url="http://192.168.1.3:8080/MyApp/messagebroker/streamamf">    
     </s:StreamingAMFChannel>    
    </s:ChannelSet> 

    <s:ChannelSet id="remotingChannelSet"> 
     <s:AMFChannel url="http://192.168.1.3:8080/MyApp/messagebroker/amf"> 
     </s:AMFChannel> 
    </s:ChannelSet> 
<s:RemoteObject id="remoteService" 
        destination="remoteService" 
        channelSet="{remotingChannelSet}">   
    </s:RemoteObject> 

var asyncCall:AsyncToken = remoteService.getTicketForCurrentUser(); 
asyncCall.addResponder(new Responder(getTicket_Result, getTicket_Fault)); 

上面的代碼總是與在cuestion開頭提到的錯誤的錯誤處理程序結束

其他配置文件:

服務-config.xml文件:

<services-config> 

<services>  
    <service-include file-path="messaging-config.xml" />   
</services> 

<channels> 
    <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"> 
     <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> 
    </channel-definition> 

    <channel-definition id="streaming-amf" class="mx.messaging.channels.StreamingAMFChannel"> 
     <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/> 
     <properties> 
      <idle-timeout-minutes>0</idle-timeout-minutes> 
      <max-streaming-clients>10</max-streaming-clients> 
      <server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis> 
      <user-agent-settings> 
       <user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="3" /> 
       <user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="3" /> 
      </user-agent-settings> 
     </properties> 
    </channel-definition>  
</channels> 

<logging> 
    <target class="flex.messaging.log.ConsoleTarget" level="Debug"> 
     <properties> 
      <prefix>[BlazeDS] </prefix> 
      <includeDate>false</includeDate> 
      <includeTime>false</includeTime> 
      <includeLevel>false</includeLevel> 
      <includeCategory>false</includeCategory> 
     </properties> 
     <filters> 
      <pattern>Endpoint.*</pattern> 
      <pattern>Service.*</pattern> 
      <pattern>Configuration</pattern> 
     </filters> 
    </target> 
</logging> 

<system> 
    <redeploy> 
     <enabled>false</enabled>   
    </redeploy> 
</system> 

messaging-config.xml:

<service id="message-service" 
class="flex.messaging.services.MessageService"> 

<adapters> 
    <adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" /> 
</adapters> 

<destination id="chat-destination"> 
    <properties> 
     <server> 
      <message-time-to-live>0</message-time-to-live> 
      <allow-subtopics>true</allow-subtopics> 
      <subtopic-separator>.</subtopic-separator> 
      <disallow-wildcard-subtopics>true</disallow-wildcard-subtopics> 
     </server>   
    </properties> 
    <channels> 
     <channel ref="streaming-amf" /> 
    </channels> 
</destination> 

<default-channels> 
    <channel ref="streaming-amf"/> 
</default-channels> 

+0

否flex代碼?如果是這樣,我可能不得不刪除這個問題的flex標籤。 – 2011-05-17 13:47:48

+0

對不起,讓我把這也 – Leo 2011-05-17 13:50:37

+0

@J_A_X Flex代碼已被添加到問題:) – Leo 2011-05-17 13:55:55

回答

3

經過對配置的深入挖掘後,我發現問題所在,我會爲每個需要它的人發佈解決方案。我必須明確地告訴Spring Security在我的「/ messagebroker/**」URL的過濾器鏈中包含「securityContextPersistenceFilter」,這樣安全上下文才能正確填充驗證信息(正如我們從一開始就假設的那樣)。配置添加到是「springSecurityFilterChain」豆如下:

<bean id="springSecurityFilterChain" 
    class="org.springframework.security.web.FilterChainProxy"> 
    <sec:filter-chain-map path-type="ant"> 
      <!-- other filter chain maps and options here (see the entire file in comment above --> 
      <sec:filter-chain 
      filters="securityContextPersistenceFilter" 
      pattern="/messagebroker/**" /> 
</bean> 

補充說,過濾器鏈配置Spring Security的過濾器從Flex UI的所有請求,其中通過從以前的登錄信息的現有身份驗證自動填充後Spring MVC Web表單。

0

爲了讓一個快速的答案 - 你可以設置你的Flex東西捎帶現有的基於HTML的Spring Security的登錄表單上?是的,絕對可以。我已經完成了它,如果你的某些應用需要受到保護,但沒有通過Flex應用提供服務,那麼它工作得非常好。

我不使用的消息,經紀人配置的

<flex:secured> 

一部分,當我第一次設置此(它不存在,也許我可以切換到它,但現在既然我的設置是工作我目前沒有強烈的需求)。我有我的我的messagebroker url模式設置爲安全。我的消息經紀人是這樣安全的:

(swf-loading-page只是一個頁面的佔位符名稱,用於包裝swf ...和。不要被映射到我的視圖解析器)

<security:intercept-url pattern="/swf-loading-page.do*" access="ROLE_USER,  
<security:intercept-url pattern="/messagebroker/**" access="ROLE_USER" /> 

當在Flex端調用:

remoteService.getTicketForCurrentUser() 

什麼被調用的Java端服務器上?

對於我的,我做同樣的事情 - 我拉出來的本地用戶將其返回到Flex客戶端(顯示登錄用戶的電流等) -

在Java方面,你可以使用SpringSecurityContextHolder得到SecurityContext中,然後從SecurityContext中,你可以拉出

//These packages are where you can hook into the authentication from your service 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.context.SecurityContext; 
import org.springframework.security.core.context.SecurityContextHolder; 
... 
SecurityContext securityContext = SecurityContextHolder.getContext(); 
Authentication authentication = securityContext.getAuthentication(); 

如果用JPDA調試您在您的應用程序服務器,你可以設置該方法中設置斷點,並瞭解你的安全上下文,並確保它正在正確填充(但它似乎不是 - 這是奇怪的)

+0

嗨@Ryan,感謝您的回答,您的解決方案按預期工作:)但我設法追蹤了我的配置上的問題,請參閱下面的評論,我會發布解決方案,以防萬一其他人遇到同樣的問題問題和我一樣。非常感謝你:) – Leo 2011-05-17 18:39:52

+0

不得不在我的解決方案這裏發表評論,因爲Stackoverflow不會讓我在8小時之前回答自己的問題。 – Leo 2011-05-17 18:49:33

+0

該解決方案涉及在Spring安全篩選器鏈中爲我的所有Flex請求添加「securityContextPersistenceFilter」。我稍後會發布整個解決方案,因爲解釋太大而不能發表評論。只要系統讓我回答我自己的問題,我會在這裏發佈 – Leo 2011-05-17 18:52:03

相關問題