什么是单点登录
单点登录(Single Sign On),简称为SSO,是目前比较流行的企业业务整合的解决方案
之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应
用系统。
什么是CAS
CAS 是Yale 大学发起的一个开源项目,旨在为Web 应用系统提供一种可靠的单点登
录方法,CAS 在2004 年12 月正式成为JA-SIG 的一个项目。CAS 具有以下特点:
【1】开源的企业级单点登录解决方案。
【2】CAS Server 为需要独立部署的Web 应用。
【2】CAS Client 支持非常多的客户端(这里指单点登录系统中的各个Web 应用),包括
Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。
从结构上看,CAS 包含两个部分: CAS Server 和CAS Client。CAS Server 需要独立部署,
主要负责对用户的认证工作;CAS Client 负责处理对客户端受保护资源的访问请求,需要登
录时,重定向到CAS Server。下图1 是CAS 最基本的协议过程:
SSO 单点登录访问流程主要有以下步骤:
1. 访问服务:SSO 客户端发送请求访问应用系统提供的服务资源。
2. 定向认证:SSO 客户端会重定向用户请求到SSO 服务器。
3. 用户认证:用户身份认证。
4. 发放票据:SSO 服务器会产生一个随机的Service Ticket。
5. 验证票据:SSO 服务器验证票据Service Ticket 的合法性,验证通过后,允许客户端访问
服务。
6. 传输用户信息:SSO 服务器验证票据通过后,传输用户认证结果信息给客户端。
CAS 服务端部署
Cas 服务端其实就是一个war 包。
在资源\cas\source\cas-server-4.0.0-release\cas-server-4.0.0\modules 目录下
cas-server-webapp-4.0.0.war 将其改名为cas.war 放入tomcat 目录下的webapps 下。启动
tomcat 自动解压war 包。浏览器输入http://localhost:8080/cas/login ,可看到登录页面
不要嫌弃这个页面丑,我们后期可以再提升它的颜值。暂时把注意力放在功能实现上。
这里有个固定的用户名和密码casuser /Mellon
在cas\WEB-INF\deployerConfigContext.xml可以设置固定的账号密码
<bean id="primaryAuthenticationHandler" class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler"> <property name="users"> <map> <entry key="casuser" value="Mellon"/> <entry key="admin" value="admin"/> </map> </property> </bean>
登录成功后会跳到登录成功的提示页面
CAS 服务端配置
端口修改
如果我们不希望用8080 端口访问CAS, 可以修改端口
(1)修改TOMCAT 的端口
打开tomcat 目录conf\server.xml 找到下面的配置
将端口8080,改为9000
(2)修改CAS 配置文件
修改cas 的WEB-INF/cas.properties
server.name=http://localhost:9000
重新启动tomcat 测试
去除https 认证
CAS 默认使用的是HTTPS 协议,如果对安全要求不高,可使用HTTP 协议。我们这里讲解通
过修改配置,让CAS 使用HTTP 协议。
(1)修改cas 的WEB-INF/deployerConfigContext.xml
找到下面的配置
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationH andler" p:httpClient-ref="httpClient"/>这里需要增加参数p:requireSecure="false",requireSecure 属性意思为是否需要安全验证,即
HTTPS,false 为不采用
(2)修改cas 的/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml
找到下面配置
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="true" p:cookieMaxAge="-1" p:cookieName="CASTGC" p:cookiePath="/cas" />参数p:cookieSecure="true",同理为HTTPS 验证相关,TRUE 为采用HTTPS 验证,FALSE 为不
采用https 验证。
参数p:cookieMaxAge="-1",是COOKIE 的最大生命周期,-1 为无生命周期,即只在当前打开
的窗口有效,关闭或重新打开其它窗口,仍会要求验证。可以根据需要修改为大于0 的数字,
比如3600 等,意思是在3600 秒内,打开任意窗口,都不需要验证。
我们这里将cookieSecure 改为false , cookieMaxAge 改为3600
(3)修改cas 的WEB-INF/spring-configuration/warnCookieGenerator.xml
找到下面配置
<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="true" p:cookieMaxAge="-1" p:cookieName="CASPRIVACY" p:cookiePath="/cas" />我们这里将cookieSecure 改为false , cookieMaxAge 改为3600
准备就绪,启动tomcat
CAS 客户端入门小Demo
搭建工程引入依赖
创建Maven 工程(war)casclient_demo1 引入cas 客户端依赖并制定tomcat 运行端口为
9001
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>casclient-test</groupId> <artifactId>casclient_demo1</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>cas单点测试1</name> <dependencies> <!-- cas --> <dependency> <groupId>org.jasig.cas.client</groupId> <artifactId>cas-client-core</artifactId> <version>3.1.12</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <!-- 指定端口--> <port>9001</port> <!-- 请求路径--> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>casclient_demo1</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 用于单点退出,该过滤器用于实现单点登出功能,可选配置--> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <!-- 该过滤器用于实现单点登出功能,可选配置。--> <filter> <filter-name>CAS Single Sign Out Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器负责用户的认证工作,必须启用它--> <filter> <filter-name>CASFilter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>http://localhost:9000/cas/login</param-value> <!--这里的server 是服务端的IP --> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:9001</param-value> </init-param> </filter> <filter-mapping> <filter-name>CASFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器负责对Ticket 的校验工作,必须启用它--> <filter> <filter-name>CAS Validation Filter</filter-name> <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class> <init-param> <param-name>casServerUrlPrefix</param-name> <param-value>http://localhost:9000/cas</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:9001</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Validation Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器负责实现HttpServletRequest 请求的包裹, 比如允许开发者通过 HttpServletRequest 的getRemoteUser()方法获得SSO 登录用户的登录名,可选配置。--> <filter> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 该过滤器使得开发者可以通过org.jasig.cas.client.util.AssertionHolder 来获取用户 的登录名。比如AssertionHolder.getAssertion().getPrincipal().getName()。--> <filter> <filter-name>CAS Assertion Thread Local Filter</filter-name> <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Assertion Thread Local Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>首页1</title> </head> <body> <%=request.getRemoteUser() %> </body> </html>request.getRemoteUser()为获取远程登录名
客户端工程2 搭建
(1)创建Maven 工程(war)casclient_demo2 引入cas 客户端依赖并制定tomcat 运行端
口为9002
(2)创建web.xml,参照casclient_demo1 ,将serverName 的值改为http://localhost:9002,
一共两处
(3)创建index.jsp ,内容显示“首页2”
单点登录测试
(1)启动cas 部署的tomcat
(2)启动客户端工程1 和客户端工程2
(3)地址栏输入http://localhost:9001/ 和http://localhost:9002/ ,地址均会跳转到CAS
登录页
(4)输入用户名和密码后,页面跳转回9002 ,再次访问9001 也可以打开主页面。
单点退出登录
地址栏输入http://localhost:9000/cas/logout
即可看到退出后的提示页面
但我们更希望退出登录后,能自动跳转到某个页面,那如何处理呢?
修改cas 系统的配置文件cas-servlet.xml
<bean id="logoutAction" class="org.jasig.cas.web.flow.LogoutAction" p:servicesManager-ref="servicesManager" p:followServiceRedirects="${cas.logout.followServiceRedirects:true}"/>改为true 后,可以在退出时跳转页面到目标页面,修改home.html 的退出链接
<a href="http://localhost:9000/cas/logout?service=http://www.baidu.com">退出登录</a>