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 在哪里?