Web服务中的Spring Security CAS实现

Posted

技术标签:

【中文标题】Web服务中的Spring Security CAS实现【英文标题】:Spring Security CAS implementation in web service 【发布时间】:2012-05-06 08:21:16 【问题描述】:

我们的团队一直致力于以某种方式保护 Web 服务,现在我们有其他使用 SpringSecurity CAS 保护的 Web 应用程序,我们认为它也可以使用它来保护 Web 服务。想法是,如果用户通过 CAS 服务器登录到其中一个 Web 应用程序,当调用 Web 服务时,它将看到该用户已经过身份验证并允许他们使用它。我们不确定这是否是正确的做法,因为有很多关于使用 HMAC 或 Oauth 2.0 的讨论,但我们想到了 CAS,因为这是其他一切都在使用的。

这是我在学习完本教程后所得到的:

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>    

不确定缺少什么或发生了什么,但是当我在 eclipse 中启动我的 tomcat 服务器时,我收到如下错误:

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

很抱歉,这太长了,但我只是想尽可能多地放在那里。

正如@smp7d 指出的那样,CAS 可能不是最好的情况。我找到了这个,

Securing REST and JSON

这正是这个 Web 服务的本质,RESTful 并提供 JSON,它将在内部托管并且只能在内部访问。现在我想问题已经从使用 CAS 转移到了我们应该使用什么,标准是什么?

谢谢

【问题讨论】:

【参考方案1】:

看来你是要参考资料...

我可以告诉您,我现在怀疑这是否存在,当我执行类似的集成时,我必须通过代码才能真正了解如何为我们的环境正确设置它。 (因为它都是开源的,所以这对你来说应该不是问题。)然后我们根据我们学到的知识创建了内部文档。这将是您需要避免尝试从现有配置中拼凑出有效实现的情况之一。有人需要完全了解实际发生的情况。

就参与 CAS 身份验证的 Web 服务而言,您需要实现类似 Restlet 的东西: https://wiki.jasig.org/display/CASUM/RESTful+API

我建议您彻底评估您的系统,以确定它是否真的需要这样的解决方案。如果您的“网络服务”调用来自浏览器,CAS 将通过正常设置来处理它(尽管您必须有创意来处理未经身份验证的情况,因为您不会重定向到登录页面)。

【讨论】:

以上是关于Web服务中的Spring Security CAS实现的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 认证 RESTful Web 服务

Rest API 中的 Spring Security Oauth2

如何在我的 Spring 4.0 RestFul Web 服务上实现 Spring Security?

Maven Repository 上 4.1.1 中的 spring-security-web 在哪里?

如何使用 Spring Security 保护 REST Web 服务

Spring MVC + Spring Security 登录与一个 REST Web 服务