大家好,又见面了,我是你们的朋友全栈君。
13.7 CAS认证
13.7.1概述
JA-SIG生产一种称为CAS的企业级单点登录系统。与其他计划不同,JA-SIG的中央身份验证服务是开源的,广泛使用的,易于理解,独立于平台,并支持代理功能。Spring Security完全支持CAS,并提供从Spring Security的单应用程序部署到企业级CAS服务器保护的多应用程序部署的轻松迁移路径。
您可以在https://www.apereo.org上了解有关CAS的更多信息。您还需要访问此站点以下载CAS Server文件。
13.7.2 CAS如何工作
虽然CAS网站包含详细说明CAS体系结构的文档,但我们在Spring Security的上下文中再次提供了一般概述。Spring Security 3.x支持CAS 3.在编写本文时,CAS服务器的版本为3.4。
在企业的某个地方,您需要设置CAS服务器。CAS服务器只是一个标准的WAR文件,因此设置服务器没有任何困难。在WAR文件中,您将自定义向用户显示的登录页面和其他单点登录页面。
部署CAS 3.4服务器时,还需要AuthenticationHandler
在deployerConfigContext.xml
CAS附带中指定一个。该AuthenticationHandler
有一个返回一个布尔值作为一组给定的证书是否有效的简单方法。您的AuthenticationHandler
实现需要链接到某种类型的后端身份验证存储库,例如LDAP服务器或数据库。CAS本身包括许多AuthenticationHandler
开箱即用的协助。下载并部署服务器war文件时,它设置为成功验证输入与其用户名匹配的密码的用户,这对测试很有用。
除CAS服务器本身外,其他主要参与者当然是整个企业中部署的安全Web应用程序。这些Web应用程序称为“服务”。有三种类型的服务。那些验证服务票证的,可以获得代理票证的那些,以及验证代理票证的那些。验证代理票证的方式不同,因为必须验证代理列表,并且通常可以重复使用代理票证。
Spring Security和CAS交互序列
Web浏览器,CAS服务器和Spring Security安全服务之间的基本交互如下:
- Web用户正在浏览服务的公共页面。不涉及CAS或Spring Security。
- 用户最终会请求一个安全的页面,或者它使用的一个bean是安全的。Spring Security
ExceptionTranslationFilter
将检测AccessDeniedException
或AuthenticationException
。 - 因为用户的
Authentication
对象(或缺少它)引起了AuthenticationException
,所以ExceptionTranslationFilter
会调用配置的AuthenticationEntryPoint
。如果使用CAS,这将是CasAuthenticationEntryPoint
该类。 - 在
CasAuthenticationEntryPoint
将用户的浏览器重定向到CAS服务器。它还将指示一个service
参数,它是Spring Security服务(您的应用程序)的回调URL。例如,浏览器重定向到的URL可能是https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas。 - 用户的浏览器重定向到CAS后,系统会提示他们输入用户名和密码。如果用户提供了一个表明他们之前已登录的会话cookie,则不会再提示他们再次登录(此过程有一个例外,我们将在后面介绍)。CAS将使用上面讨论的
PasswordHandler
(或AuthenticationHandler
使用CAS 3.0)来确定用户名和密码是否有效。 - 成功登录后,CAS会将用户的浏览器重定向回原始服务。它还将包含一个
ticket
参数,该参数是表示“服务票证”的不透明字符串。继续我们之前的示例,浏览器重定向到的URL可能是https://server3.company.com/webapp/login/cas?ticket=ST-0-ER94xMJmn6pha35CQRoZ。 - 回到服务Web应用程序,
CasAuthenticationFilter
总是在监听请求/login/cas
(这是可配置的,但我们将使用本简介中的默认值)。处理过滤器将构造UsernamePasswordAuthenticationToken
表示服务票证的过程。委托人将等于CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER
,而凭证将是服务票不透明值。然后,此身份验证请求将传递给已配置的AuthenticationManager
。 - 该
AuthenticationManager
实施将是ProviderManager
,其又配置了CasAuthenticationProvider
。将CasAuthenticationProvider
只响应UsernamePasswordAuthenticationToken
包含CAS特异性主要(如SCasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER
)和CasAuthenticationToken
S(稍后讨论)。 CasAuthenticationProvider
将使用TicketValidator
实现验证服务票证。这通常是Cas20ServiceTicketValidator
CAS客户端库中包含的类之一。如果应用程序需要验证代理票证,Cas20ProxyTicketValidator
则使用该代理票证。在TicketValidator
以验证服务票证发出HTTPS请求到CAS服务器。它还可能包含代理回调URL,该URL包含在此示例中:https://my.company.com/cas/proxyValidate?service = https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas&ticket= ST-0-ER94xMJmn6pha35CQRoZ&pgtUrl = https://server3.company.com/webapp/login/cas/proxyreceptor。- 返回CAS服务器,将收到验证请求。如果提供的服务票证与发出票证的服务URL相匹配,CAS将以XML格式提供肯定响应,指示用户名。如果身份验证中涉及任何代理(如下所述),则代理列表也包含在XML响应中。
- [可选]如果对CAS验证服务的请求包含代理回调URL(在
pgtUrl
参数中),CAS将pgtIou
在XML响应中包含一个字符串。这pgtIou
表示代理授予票证IOU。然后CAS服务器将创建自己的HTTPS连接回pgtUrl
。这是为了相互验证CAS服务器和声明的服务URL。HTTPS连接将用于将代理授予票证发送到原始Web应用程序。例如,https://server3.company.com/webapp/login/cas/proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH。 - 该
Cas20TicketValidator
会解析从CAS服务器接收到的XML。它将返回到CasAuthenticationProvider
aTicketResponse
,其中包括用户名(必填),代理列表(如果涉及)和代理授予票证IOU(如果请求代理回调)。 - 接下来
CasAuthenticationProvider
将调用已配置的CasProxyDecider
。该CasProxyDecider
指示在代理列表是否TicketResponse
是可以接受的服务。多次实现Spring Security提供:RejectProxyTickets
,AcceptAnyCasProxy
和NamedCasProxyDecider
。这些名称在很大程度上是不言自明的,除了NamedCasProxyDecider
允许提供List
可信代理。 CasAuthenticationProvider
接下来将请求AuthenticationUserDetailsService
加载GrantedAuthority
适用于包含在中的用户的对象Assertion
。- 如果没有问题,
CasAuthenticationProvider
构建一个CasAuthenticationToken
包含TicketResponse
和GrantedAuthority
s中包含的细节。 - 然后控制返回到
CasAuthenticationFilter
,将创建的内容CasAuthenticationToken
放在安全上下文中。 - 用户的浏览器将重定向到导致
AuthenticationException
(或自定义目标取决于配置)的原始页面。
你还在这里真好!我们现在来看看它是如何配置的
13.7.3 CAS客户端的配置
由于Spring Security,CAS的Web应用程序端变得简单。假设您已经了解使用Spring Security的基础知识,因此下面不再介绍这些内容。我们假设正在使用基于命名空间的配置,并根据需要添加CAS bean。每个部分都基于上一部分。可以在Spring Security Samples中找到完整的CAS示例应用程序。
服务票证认证
本节介绍如何设置Spring Security以验证服务票证。通常,这是Web应用程序所需的全部内容。您需要将ServiceProperties
bean 添加到应用程序上下文中。这代表您的CAS服务:
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://localhost:8443/cas-sample/login/cas"/>
<property name="sendRenew" value="false"/>
</bean>
本service
必须是一个被监控的URL CasAuthenticationFilter
。该sendRenew
应用是否特别敏感默认为false,但应设置为true。此参数的作用是告诉CAS登录服务单点登录是不可接受的。相反,用户需要重新输入用户名和密码才能访问该服务。
应配置以下bean以启动CAS身份验证过程(假设您正在使用命名空间配置):
<security:http entry-point-ref="casEntryPoint">
...
<security:custom-filter position="CAS_FILTER" ref="casFilter" />
</security:http>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://localhost:9443/cas/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>
要使CAS运行,ExceptionTranslationFilter
必须将其authenticationEntryPoint
属性设置为CasAuthenticationEntryPoint
bean。这可以使用入口点ref轻松完成,如上例所示。在CasAuthenticationEntryPoint
必须引用ServiceProperties
豆(如上所述),它提供的URL企业CAS登录服务器。这是用户浏览器重定向的位置。
它CasAuthenticationFilter
具有非常相似的属性UsernamePasswordAuthenticationFilter
(用于基于表单的登录)。您可以使用这些属性来自定义身份验证成功和失败等行为。
接下来,您需要添加一个CasAuthenticationProvider
及其协作者:
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://localhost:9443/cas" />
</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>
<security:user-service id="userService">
<!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
NoOpPasswordEncoder should be used.
This is not safe for production, but makes reading
in samples easier.
Normally passwords should be hashed using BCrypt -->
<security:user name="joe" password="{noop}joe" authorities="ROLE_USER" />
...
</security:user-service>
该CasAuthenticationProvider
使用UserDetailsService
实例来加载当局用户,一旦他们被CAS认证。我们在这里展示了一个简单的内存设置。请注意,CasAuthenticationProvider
实际上并不使用密码进行身份验证,但它确实使用了权限。
如果您再参考CAS工作原理部分,那么这些bean都是相当不言自明的。
这样就完成了CAS的最基本配置。如果您没有犯任何错误,您的Web应用程序应该在CAS单点登录框架内愉快地工作。Spring Security的其他任何部分都不需要担心CAS处理身份验证的事实。在以下部分中,我们将讨论一些(可选)更高级的配置。
单点注销
CAS协议支持单点注销,可以轻松添加到Spring Security配置中。以下是处理Single Logout的Spring Security配置的更新
<security:http entry-point-ref="casEntryPoint">
...
<security:logout logout-success-url="/cas-logout.jsp"/>
<security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</security:http>
<!-- This filter handles a Single Logout Request from the CAS Server -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
<!-- This filter redirects to the CAS Server to signal Single Logout should be performed -->
<bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="https://localhost:9443/cas/logout"/>
<constructor-arg>
<bean class=
"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout/cas"/>
</bean>
该logout
元素将用户从本地应用程序中注销,但不会终止与CAS服务器或已登录的任何其他应用程序的会话。该requestSingleLogoutFilter
过滤器将允许的URL /spring_security_cas_logout
被请求重定向到应用程序的配置CAS服务器注销URL。然后CAS服务器将向登录的所有服务发送Single Logout请求。该singleLogoutFilter
处理通过查找单注销请求HttpSession
静态Map
,然后无效的。
可能会混淆为什么需要logout
元素和元素singleLogoutFilter
。首先在本地注销是最佳实践,因为SingleSignOutFilter
只是将其存储HttpSession
在静态Map
中以便在其上调用invalidate。通过上面的配置,注销流程将是:
- 用户请求
/logout
将用户从本地应用程序中注销并将用户发送到注销成功页面。 - 注销成功页面
/cas-logout.jsp
应指示用户单击指向的链接/logout/cas
以退出所有应用程序。 - 当用户单击该链接时,该用户将被重定向到CAS单一注销URL(https:// localhost:9443 / cas / logout)。
- 在CAS服务器端,CAS单一注销URL然后向所有CAS服务提交单个注销请求。在CAS服务方面,JASIG
SingleSignOutFilter
通过使原始会话无效来处理注销请求。
下一步是将以下内容添加到web.xml中
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
</listener-class>
</listener>
使用SingleSignOutFilter时,您可能会遇到一些编码问题。因此,建议添加CharacterEncodingFilter
以确保使用时字符编码正确SingleSignOutFilter
。再次,请参阅JASIG的文档以获取详细信息。的SingleSignOutHttpSessionListener
确保,当HttpSession
期满时,用于单注销的映射被去除。
使用CAS对无状态服务进行身份验证
本节介绍如何使用CAS对服务进行身份验证。换句话说,本节讨论如何设置使用通过CAS进行身份验证的服务的客户端。下一节将介绍如何使用CAS设置无状态服务以进行身份验证。
配置CAS以获取代理授予票证
为了对无状态服务进行身份验证,应用程序需要获取代理授予票证(PGT)。本节介绍如何配置Spring Security以获取基于thencas-st [Service Ticket Authentication]配置的PGT构建。
第一步是ProxyGrantingTicketStorage
在Spring Security配置中包含一个。这用于存储通过CasAuthenticationFilter
它们获得的PGT,以便它们可用于获取代理票据。示例配置如下所示
<!--
NOTE: In a real application you should not use an in memory implementation.
You will also want to ensure to clean up expired tickets by calling
ProxyGrantingTicketStorage.cleanup()
-->
<bean id="pgtStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/>
下一步是更新CasAuthenticationProvider
以获得代理票证。要做到这一点,请Cas20ServiceTicketValidator
用a 替换Cas20ProxyTicketValidator
。该proxyCallbackUrl
应设置为应用程序将获得PGT的一个URL。最后,配置也应该引用ProxyGrantingTicketStorage
它,以便它可以使用PGT来获取代理票据。您可以在下面找到应该进行的配置更改的示例。
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<constructor-arg value="https://localhost:9443/cas"/>
<property name="proxyCallbackUrl"
value="https://localhost:8443/cas-sample/login/cas/proxyreceptor"/>
<property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
</bean>
</property>
</bean>
最后一步是更新CasAuthenticationFilter
接受PGT并将它们存储在ProxyGrantingTicketStorage
。这一点很重要的proxyReceptorUrl
比赛proxyCallbackUrl
的Cas20ProxyTicketValidator
。示例配置如下所示。
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
...
<property name="proxyGrantingTicketStorage" ref="pgtStorage"/>
<property name="proxyReceptorUrl" value="/login/cas/proxyreceptor"/>
</bean>
使用代理票证调用无状态服务
现在Spring Security获得了PGT,您可以使用它们来创建可用于对无状态服务进行身份验证的代理票据。该CAS示例应用程序包含了一个工作示例ProxyTicketSampleServlet
。示例代码可以在下面找到:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// NOTE: The CasAuthenticationToken can also be obtained using
// SecurityContextHolder.getContext().getAuthentication()
final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
// proxyTicket could be reused to make calls to the CAS service even if the
// target url differs
final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);
// Make a remote call using the proxy ticket
final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
...
}
代理票证认证
的CasAuthenticationProvider
状态和无状态的客户进行了区分。一个有状态的客户机被认为是任何提交给filterProcessUrl
的CasAuthenticationFilter
。无状态客户端是指向CasAuthenticationFilter
除了以外的URL 的身份验证请求的任何客户端filterProcessUrl
。
由于远程处理协议无法在a的上下文中呈现自身HttpSession
,因此不可能依赖于在请求之间的会话中存储安全性上下文的默认实践。此外,由于CAS服务器在经过验证后使其无效,因此TicketValidator
在后续请求中显示相同的代理票证将不起作用。
一个显而易见的选择是根本不使用CAS来远程协议客户端。但是,这将消除CAS的许多理想特征。作为中间地带,CasAuthenticationProvider
使用a StatelessTicketCache
。这仅用于使用等于的主体的无状态客户端CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER
。会发生什么事是CasAuthenticationProvider
将存储所产生CasAuthenticationToken
的StatelessTicketCache
,键上的代理票。因此,远程协议客户端可以呈现相同的代理票证,并且CasAuthenticationProvider
不需要联系CAS服务器进行验证(除了第一个请求之外)。经过身份验证后,代理票证可用于除原始目标服务之外的URL。
本节以前面的部分为基础,以适应代理票证身份验证。第一步是指定验证所有工件,如下所示。
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
...
<property name="authenticateAllArtifacts" value="true"/>
</bean>
下一步是指定serviceProperties
和authenticationDetailsSource
为CasAuthenticationFilter
。该serviceProperties
属性指示CasAuthenticationFilter
尝试对所有工件进行身份验证,而不是仅对存在的工件进行身份验证filterProcessUrl
。在ServiceAuthenticationDetailsSource
一个创建ServiceAuthenticationDetails
,以确保当前的URL,基于HttpServletRequest
被验证检票时使用的服务URL。可以通过注入AuthenticationDetailsSource
返回自定义的自定义来自定义用于生成服务URL的方法ServiceAuthenticationDetails
。
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
...
<property name="serviceProperties" ref="serviceProperties"/>
<property name="authenticationDetailsSource">
<bean class=
"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource">
<constructor-arg ref="serviceProperties"/>
</bean>
</property>
</bean>
您还需要更新CasAuthenticationProvider
处理代理票证。要做到这一点,请Cas20ServiceTicketValidator
用a 替换Cas20ProxyTicketValidator
。您需要配置statelessTicketCache
要接受的代理和代理。您可以找到接受以下所有代理所需的更新示例。
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
...
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator">
<constructor-arg value="https://localhost:9443/cas"/>
<property name="acceptAnyProxy" value="true"/>
</bean>
</property>
<property name="statelessTicketCache">
<bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache">
<property name="cache">
<bean class="net.sf.ehcache.Cache"
init-method="initialise" destroy-method="dispose">
<constructor-arg value="casTickets"/>
<constructor-arg value="50"/>
<constructor-arg value="true"/>
<constructor-arg value="false"/>
<constructor-arg value="3600"/>
<constructor-arg value="900"/>
</bean>
</property>
</bean>
</property>
</bean>
原文:https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#cas
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/149087.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...