CAS客户端也是可以与各种软件平台和应用程序集成的软件包,以便使用或者更多支持的协议与CAS服务器通信。已经开发了支持许多软件平台和产品的CAS客户。
其他非官方或孵化的CAS客户可以在这里找到。鉴于上述项目是非官方的,不受CAS的直接维护,其可用性和准确性可能会有所不同。
以下编程框架内置了对CAS的支持:
由于许多CAS客户已经存在,因此开发CAS客户端的机会很少,应该尽可能避免。实际上,创建自己的客户端并不是一件容易的事,而且最有可能产生安全漏洞。
但是,如果您确实需要创建自己的CAS客户端,请注意以下不完整的指导原则:
。。。。。。
此配置针对Spring Security附带的示例应用程序进行了测试。在撰写本文时,applicationContext-security.xml
使用下面的示例应用程序替换示例应用程序将启用此替代配置。我们无法保证此版本在未经修改的Spring Security版本中无需修改即可使用。
...
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>cas.root</param-value>
</context-param>
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>https://cas.example.com/cas</param-value>
</init-param>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<error-page>
<error-code>403</error-code>
<location>/casfailed.jsp</location>
</error-page>
...
对此的重要补充web.xml
包括添加403错误页面。403是CAS验证过滤器在票证出现问题时将抛出的内容。此外,如果您想要单一注销,您应该启用SingleSignOutHttpSessionListener
。
...
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/" filters="casValidationFilter, wrappingFilter" />
<sec:filter-chain pattern="/secure/receptor" filters="casValidationFilter" />
<sec:filter-chain pattern="/j_spring_security_logout" filters="logoutFilter,etf,fsi" />
<sec:filter-chain pattern="/**" filters="casAuthenticationFilter, casValidationFilter, wrappingFilter, sif,j2eePreAuthFilter,logoutFilter,etf,fsi"/>
</sec:filter-chain-map>
</bean>
<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="preAuthAuthProvider"/>
</sec:authentication-manager>
<bean id="preAuthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="userService"/>
</bean>
</property>
</bean>
<bean id="preAuthEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<bean id="j2eePreAuthFilter" class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationDetailsSource">
<bean class="org.springframework.security.web.authentication.WebAuthenticationDetailsSource" />
</property>
</bean>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/"/>
<constructor-arg>
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
<bean id="etf" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="preAuthEntryPoint"/>
</bean>
<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>
<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadataSource">
<sec:filter-invocation-definition-source>
<sec:intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>
<sec:intercept-url pattern="/secure/**" access="ROLE_USER"/>
<sec:intercept-url pattern="/**" access="ROLE_USER"/>
</sec:filter-invocation-definition-source>
</property>
</bean>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator" id="ticketValidator">
<constructor-arg index="0" value="https://localhost:9443/cas" />
<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
<property name="proxyCallbackUrl" value="https://localhost:8443/cas-sample/secure/receptor" />
</bean>
<bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
<sec:user-service id="userService">
<sec:user name="rod" password="rod" authorities="ROLE_SUPERVISOR,ROLE_USER" />
<sec:user name="dianne" password="dianne" authorities="ROLE_USER" />
<sec:user name="scott" password="scott" authorities="ROLE_USER" />
</sec:user-service>
<bean id="casAuthenticationFilter" class="org.jasig.cas.client.authentication.AuthenticationFilter">
<property name="casServerLoginUrl" value="https://localhost:9443/cas/login" />
<property name="serverName" value="https://localhost:8443" />
</bean>
<bean id="casValidationFilter" class="org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter">
<property name="serverName" value="https://localhost:8443" />
<property name="exceptionOnValidationFailure" value="true" />
<property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" />
<property name="redirectAfterValidation" value="true" />
<property name="ticketValidator" ref="ticketValidator" />
<property name="proxyReceptorUrl" value="/secure/receptor" />
</bean>
<bean id="wrappingFilter" class="org.jasig.cas.client.util.HttpServletRequestWrapperFilter" />
...
userService
用于检查用户存储的内容。serverName
和casServerLoginUrl
您的值(或更好,外化它们)。原文:
https://apereo.github.io/cas/5.2.x/integration/CAS-Clients.html