3 votes

Implémentation de Spring Security CAS dans un service web

Notre équipe a été chargée de sécuriser un service web d'une manière ou d'une autre. Nous avons maintenant d'autres applications web qui sont sécurisées avec SpringSecurity CAS, et nous avons pensé qu'il serait possible de sécuriser le service web avec ce système également. L'idée est que si l'utilisateur se connecte à l'une des applications web via le serveur CAS, lorsque le service web est appelé, il verra que l'utilisateur est déjà authentifié et lui permettra de l'utiliser. Nous ne sommes pas vraiment sûrs que ce soit la bonne façon de procéder, car il a été beaucoup question d'utiliser HMAC ou Oauth 2.0, mais nous avons pensé à CAS parce que c'est ce que tout le reste utilise.

Voici ce que j'ai obtenu jusqu'à présent après avoir suivi ce tutoriel :

http://www.oudmaijer.com/2009/12/28/spring-3-spring-security-3-cas-3-3-4-integration/

pom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>3.0.0.RELEASE</version>
    <optional>false</optional>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>3.0.0.RELEASE</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-cas-client</artifactId>
    <version>3.0.0.RELEASE</version>
    <optional>false</optional>
</dependency>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
        id="WebApp_ID" 
        version="2.5">
<display-name>webservice</display-name>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
    <servlet-name>service</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>service</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Start Spring CAS integration -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/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>

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- End Spring CAS integration -->

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" 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.xsd">

<!--
    Enable security, let the casAuthenticationEntryPoint handle all intercepted urls.
    The CAS_FILTER needs to be in the right position within the filter chain.
-->
<security:http entry-point-ref="casAuthenticationEntryPoint" auto-config="true">
    <security:intercept-url pattern="/**" access="ROLE_USER"></security:intercept-url>
    <security:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter"></security:custom-filter>
</security:http>

<!--
    Required for the casProcessingFilter, so define it explicitly set and
    specify an Id Even though the authenticationManager is created by
    default when namespace based config is used.
-->
<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="casAuthenticationProvider"></security:authentication-provider>
</security:authentication-manager>

<!--
    This section is used to configure CAS. The service is the
    actual redirect that will be triggered after the CAS login sequence.
-->
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
    <property name="service" value="http://localhost:8080/service/j_spring_cas_security_check"></property>
    <property name="sendRenew" value="false"></property>
</bean> 

    <!--
    The CAS filter handles the redirect from the CAS server and starts the ticket validation.
-->
<bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager"></property>
</bean>

<!--
    The entryPoint intercepts all the CAS authentication requests.
    It redirects to the CAS loginUrl for the CAS login page.
-->
<bean id="casAuthenticationEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
    <property name="loginUrl" value=""></property>
    <property name="serviceProperties" ref="serviceProperties"></property>
</bean>

<!--
    Handles the CAS ticket processing.
 -->
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
    <property name="userDetailsService" ref="userService"></property>
    <property name="serviceProperties" ref="serviceProperties"></property>
    <property name="ticketValidator">
        <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
            <constructor-arg index="0" value=""></constructor-arg>
        </bean>
    </property>
    <property name="key" value="cas"></property>
</bean>

<!--
    The users available for this application.
-->
<security:user-service id="userService">
    <security:user name="user" password="user" authorities="ROLE_USER"></security:user>
</security:user-service>    

Je ne suis pas sûr de ce qui manque ou de ce qui se passe, mais lorsque je démarre mon serveur tomcat dans eclipse, j'obtiens une erreur telle que :

ERROR 2012-04-25 09:24:33 Context initialization failed
java.lang.NoClassDefFoundError: org/springframework/core/convert/support/PropertyTypeDescriptor
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1003)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:907)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:722)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:410)
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 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
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:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: java.lang.ClassNotFoundException: org.springframework.core.convert.support.PropertyTypeDescriptor
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
... 29 more
Apr 25, 2012 9:24:33 AM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class  org.springframework.web.context.ContextLoaderListener 
java.lang.NoClassDefFoundError: org/springframework/core/convert/support/PropertyTypeDescriptor
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1003)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:907)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:722)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:410)
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 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
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:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: java.lang.ClassNotFoundException: org.springframework.core.convert.support.PropertyTypeDescriptor
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
... 29 more
Apr 25, 2012 9:24:33 AM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
Apr 25, 2012 9:24:33 AM org.apache.catalina.core.StandardContext start
SEVERE: Context [/bannernotifications] startup failed due to previous errors
Apr 25, 2012 9:24:33 AM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Apr 25, 2012 9:24:33 AM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Apr 25, 2012 9:24:33 AM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Apr 25, 2012 9:24:33 AM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/15  config=null
Apr 25, 2012 9:24:33 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 855 ms

Je suis désolé que ce soit si long, mais je voulais juste en dire le plus possible.

Comme @smp7d l'a souligné, le CAS n'est peut-être pas le meilleur cas pour cela. J'ai trouvé ceci,

Sécuriser REST et JSON

qui est exactement ce qu'est ce service web, RESTful et servant JSON, il va être hébergé en interne et seulement accessible en interne. Maintenant, je suppose que la question est passée de l'utilisation de CAS à ce que nous devrions faire, quel est le standard ?

Merci

0voto

smp7d Points 2948

Il semble que vous demandiez des documents de référence...

Je peux vous dire que je doute que cela existe pour le moment, lorsque j'ai effectué une intégration similaire, j'ai dû parcourir le code pour vraiment comprendre comment le configurer correctement pour notre environnement. (Nous avons ensuite créé une documentation interne basée sur ce que nous avons appris. Il s'agit de l'un de ces cas où vous devez vous abstenir d'essayer d'assembler une implémentation fonctionnelle à partir d'une configuration existante. Il faut que quelqu'un comprenne parfaitement ce qui se passe réellement.

Pour ce qui est d'un service Web qui participe à l'authentification CAS, il faudrait mettre en œuvre quelque chose comme un Restlet : https://wiki.jasig.org/display/CASUM/RESTful+API

Je vous suggère d'évaluer votre système en profondeur pour décider s'il a vraiment besoin d'une telle solution. Si vos appels de "service web" proviennent d'un navigateur, le CAS les traitera par le biais de la configuration normale (bien que vous deviez faire preuve de créativité pour gérer les cas non authentifiés, car vous ne serez pas redirigé vers une page de connexion).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X