Announcement Announcement Module
Collapse
No announcement yet.
Remote Swing Client and Webapp Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Remote Swing Client and Webapp

    Hello, I am setting up spring security on my server and need to allow a web application and a swing remote client to access my business services layer. Being a spring newbie I thought I should ask if I have set things up correctly or if I am making terrible mistakes in my configuration.

    Two things I have noticed, but don't know if they are because I am doing something wrong or not, are that the remote client doesn't get a populated Authentication object like the server does and, possibly more importantly, I cannot use concurrent session control with my remoteAuthenticationManager from the swing client.

    On my server I have a HelloService that returns a greeting such as "Hello" + name + "!" from its single sayHello(String name) method.

    My web.xml:
    Code:
      <!--
        Location of the XML file that defines the root application context.
        Applied by ContextLoaderListener.
    	-->
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
          /WEB-INF/applicationContext.xml,
          /WEB-INF/applicationContext-security.xml
        </param-value>
      </context-param>
    
      <listener>
        <listener-class>
          org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
    
      <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>
    
      <servlet>
        <servlet-name>remoting</servlet-name>
        <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>remoting</servlet-name>
        <url-pattern>/remoting/*</url-pattern>
      </servlet-mapping>
    
      <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.html</url-pattern>
      </servlet-mapping>
    
      <!--
        Loads the root application context of this web app at startup. The
        application context is then available via
        WebApplicationContextUtils.getWebApplicationContext(servletContext).
      -->
      <listener>
        <listener-class>
          org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
    
      <!--
        Publishes events for session creation and destruction through the
        application context. Optional unless concurrent session control is being
        used.
      -->
      <listener>
        <listener-class>
          org.springframework.security.ui.session.HttpSessionEventPublisher
        </listener-class>
      </listener>
      
      <session-config>
        <session-timeout>1</session-timeout>
      </session-config>
    
      <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
      </welcome-file-list>
            
    </web-app>
    My dispatcher-servlet.xml:
    Code:
      <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
      <!--<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>-->
        
      <!--
       Most controllers will use the ControllerClassNameHandlerMapping above, but
       for the index controller we are using ParameterizableViewController, so we
       must define an explicit mapping for it.
      -->
      <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
          <props>
            <prop key="/index.html">indexController</prop>
            <prop key="/secure/hello.html">helloController</prop>
          </props>
        </property>
      </bean>
    
      <!--
        Translates view names to the proper URL for the view by contatenating a
        prefix and suffix onto the view name.  So, a view named "customers" would be
        translated into "/WEB-INF/jsp/customers.jsp".
      -->
      <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/jsp/"
        p:suffix=".jsp" />
        
      <!--
        The index controller.
      -->
      <bean id="indexController"
        class="org.springframework.web.servlet.mvc.ParameterizableViewController"
        p:viewName="index"/>
    
      <!--
        The hello controller.
      -->
      <bean id="helloController" class="webtest.controller.HelloController">
        <property name="helloService" ref="helloService"/>
      </bean>
        
    </beans>
    My remoting-servlet.xml:
    Code:
      <!--
        Export the remote authentication manager service via an HttpInvoker.
    
        Use bean name instead of id to properly map the name to a URL.
      -->
      <bean name="/RemoteAuthenticationManager.html" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service" ref="remoteAuthenticationManager"/>
        <property name="serviceInterface" value="org.springframework.security.providers.rcp.RemoteAuthenticationManager"/>
      </bean>
    
      <!--
        Export our hello service via an HttpInvoker.
    
        Use bean name instead of id to properly map the name to a URL.
      -->
      <bean name="/HelloService-http.html" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service" ref="helloService"/>
        <property name="serviceInterface" value="webtest.service.HelloService"/>
      </bean>
        
    </beans>
    My server applicationContext.xml:
    Code:
      <bean id="messageEventListener" class="MessageEventListener"/>
    
      <!--
        Create an alias to the authentication manager for use by other beans.
      -->
      <security:authentication-manager alias="authenticationManager"/>
    
      <bean id="remoteAuthenticationManager" class="org.springframework.security.providers.rcp.RemoteAuthenticationManagerImpl">
        <property name="authenticationManager" ref="authenticationManager"/>
      </bean>
    
      <bean id="helloService" class="webtest.service.HelloServiceImpl"/>
        
    </beans>
    My server applicationContext-security.xml:
    Code:
      <!--
        Enable method level annotation security.  Secures methods annotated with the
        @Secured, @SecureObject, @Filter, etc. annotations.
      -->
      <!--<global-method-security secured-annotations="enabled"/>-->
    
      <!--
        This will protect all methods on beans declared in the application context
        whose classes are in the webtest.service package and whose class names end in
        "Service".  Only users with the ROLE_ADMIN role will be able to invoke these
        methods. As with URL matching, the most specific matches must come first in
        the list of pointcuts, as the first matching expression will be used.
      -->
      <global-method-security>
        <protect-pointcut expression="execution(* webtest.service.*Service.*(..))" access="ROLE_ADMIN"/>
        <!--<protect-pointcut expression="execution(* webtest.service.HelloService.sayHello(..))" access="ROLE_ADMIN"/>-->
      </global-method-security>
    
      <http auto-config="false" create-session="always" once-per-request="false" realm="Test Realm">
        <!--<concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>-->
        <anonymous/>
        <http-basic/>
        <logout logout-url="/logout.html"/>
    
        <port-mappings>
          <port-mapping http="8080" https="8181"/>
        </port-mappings>
    
        <intercept-url pattern="/index.htm*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <intercept-url pattern="/remoting/RemoteAuthenticationManager.html" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
        <intercept-url pattern="/remoting/**" access="ROLE_USER" requires-channel="https"/>
        <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
      </http>
    
      <ldap-server url="ldap://myActiveDirectory:389/dc=myCompany,dc=org"
        manager-dn="CN=myManagerLogin,OU=Users,DC=myCompany,DC=org"
        manager-password="secret"/>
      <ldap-authentication-provider
        user-search-base="OU=Staff"
        user-search-filter="(sAMAccountName={0})"
        group-search-base="OU=Groups,OU=Users"
        group-search-filter="member={0}"/>
    
    </beans:beans>
    Running this from a web browser, everything appears to work correctly. But from the remote client I can't enforce concurrent session control. This only concerns me as I have read that the correct way to set up remote client authentication and remoting when using http for the remoting is to use BASIC authentication. Since this requires the login/password on every request I need to use https to hide the password and don't want to have to keep renegotiating https sessions.

    I would also like to have control somehow to enforce a user being logged in only once.

    I am only assuming I am doing things the preferred way at this point anyway, I suppose its possible I may not need to worry about concurrent session control. *shrug* I guess I could be doing it all wrong, if so, please tell me I suck at this and how to get better.

  • #2
    Here is my swing client applicationContext.xml In case I've screwed that up too.

    Code:
      <bean id="main" class="webremoteclient.Main">
        <property name="loginPane" ref="loginPane"/>
      </bean>
    
      <bean id="loginPane" class="org.jdesktop.swingx.JXLoginPane">
        <property name="loginService" ref="loginService"/>
      </bean>
    
      <bean id="loginService" class="webremoteclient.SpringLoginService">
        <property name="loginPane" ref="loginPane"/>
        <property name="remoteAuthenticationManager" ref="remoteAuthenticationManager"/>
      </bean>
    
      <bean id="remoteAuthenticationManager" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl" value="https://localhost:8181/WebTest/remoting/RemoteAuthenticationManager.html"/>
        <property name="serviceInterface" value="org.springframework.security.providers.rcp.RemoteAuthenticationManager"/>
      </bean>
    
      <bean id="helloService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl" value="http://localhost:8080/WebTest/remoting/helloService-http.html"/>
        <property name="serviceInterface" value="webremoteclient.HelloService"/>
        <property name="httpInvokerRequestExecutor" ref="BasicAuthenticationRequestExecutor"/>
      </bean>
    
      <bean id="BasicAuthenticationRequestExecutor" class="webremoteclient.BasicAuthenticationCommonsHttpInvokerRequestExecutor"/>
        
    </beans>
    Any help, advice or constructive criticism would be very appreciated.
    Last edited by adamarmistead; Apr 20th, 2009, 02:19 PM.

    Comment


    • #3
      i am also planing to do something like you have done but i will be using rmi call in place of HTTP invoker. Can you please tell me if this works? as i haven't seen any example of using rmi for the same remote login thing.

      Comment


      • #4
        sachin,

        sorry, I have only tried authenticating with HttpInvoker by adding the username/password to the http headers. As to how to do it with RMI, the only thing I have found on a quick search is this reference:

        http://static.springframework.org/sp.../remoting.html

        As stated in section 17.2:
        "...there is no standard support for security context propagation or remote transaction propagation. Spring does provide hooks for such additional invocation context when using the RMI invoker, so you can for example plug in security frameworks or custom security credentials here."

        So it can be done. I just don't know how, without researching it.

        Comment


        • #5
          Ok, thanks for your reply. I will try this.

          Comment

          Working...
          X