【转】CAS技术原理及分析
http://blog.****.net/sjbup/article/details/7454068
CAS实现原理:
认证流程分析:
1:用户第一次访问受保护的应用。受保护的应用通过其中配置的统一认证过滤器队请求进行过滤,未发现在session中有特定的用户信息,也未发现有ST参数。
2:应用系统将认定用户第一次进入受保护的系统中,重定向到统一认证系统中特定的路径。通常该路径为 http:// 统一认证IP:端口/casserver/login
3:统一认证系统判断用户在统一认证系统中是否登录过。
4:如果没有登录过,则将用户定向到登录界面。
5:用户在登录界面输入用户名和密码等信息,并进行提交。
6:统一认证系统验证用户提交的凭证是否正确,如果正确,生成cookie形式的TGT(ticket grant ticket)和一个ST(service ticket)。并通过重定向跳回到受保护的系统中。并且,将ST作为参数附加在URL后面。
7:进入受保护系统中,请求经由统一认证过滤器进行过滤,发现虽然在session中不存在特定的用户信息,但是存在ST票据。
8:有统一认证客户端持有ST票据通过http请求,发送到统一认证端进行认证票据的有效性。
9:统一认证系统认证票据有效,相应用户信息到受保护系统。
10:受保护系统获得用户信息,在session中设置特定的用户信息。返回用户访问资源。
理解了CAS实现单点登录的原理之后,我们就来看一下CAS服务器端的整体结构:
分析web工程一般都是从web.xml文件开始进行分析的。我们就先来看一下web.xml
首先是spring进行控制反转控制的配置文件。通常使用过spring的开发人员应该对spring会比较了解,这里先不解释,以后的分析中,会对spring的两大特性IOC和AOP进行相应的分析。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-configuration/*.xml
/WEB-INF/deployerConfigContext.xml
</param-value>
</context-param>
第二部分是CAS的日志文件的配置。这个方面以后将会作为一个知识点进行相对系统的分析。
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.xml</param-value>
</context-param>
<context-param>
<param-name>log4jExposeWebAppRoot</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
下面是CAS自身业务相关的重点了。
<filter>
<filter-name>CAS Client Info Logging Filter</filter-name>
<filter-class>com.github.inspektr.common.web.ClientInfoThreadLocalFilter</filter-class>
</filter>
该filter主要是对进入CAS自身的接入系统管理的请求进行过滤的。该过滤主要是采用springsecurity框架来处理的。这会在将来也会作为一个知识点进行重点分析。
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
该过滤器是对请求的字符编码就行处理的过滤器。相信大家都会很熟悉。
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/services/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Client Info Logging Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这里是对日志初始化相关的监听器。将会在日志部分重点分析。(其实不光是有日志,还有性能分析。)
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>
org.jasig.cas.web.init.SafeContextLoaderListener
</listener-class>
</listener>
这里是CAS进行统一认证的重点部分。和认证相关的请求都是由这个servlet进行处理的。
<servlet>
<servlet-name>cas</servlet-name>
<servlet-class>
org.jasig.cas.web.init.SafeDispatcherServlet
</servlet-class>
<init-param>
<param-name>publishContext</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/validate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/serviceValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/samlValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/proxyValidate</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/CentralAuthenticationService</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/add.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/viewStatistics.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/logout.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/loggedOut.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/manage.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/edit.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/openid/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/services/deleteRegisteredService.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/authorizationFailure.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cas</servlet-name>
<url-pattern>/403.html</url-pattern>
</servlet-mapping>
<session-config>
<!-- Default to 5minute session timeouts -->
<session-timeout>5</session-timeout>
</session-config>
<error-page>
<exception-type>org.springframework.context.ApplicationContextException</exception-type>
<location>/WEB-INF/view/jsp/brokenContext.jsp</location>
</error-page>
注意:一个filter和一个servlet是可以对多个路径进行过滤的。所以,遇到一个servlet处理多个路径的时候,最好不要尝试拦截所有请求路径,然后在servlet和filter中进行区分处理,这样效率是会很低的。可以多些几个filtermapping,多些几个servletmapping。虽然让web.xml看上去复杂很多,但效率会高出很多。