我们在上一篇文章中已经介绍了cas以及它的工作流程。
单点登录(一)-----理论-----单点登录SSO的介绍和CAS+选型
本章我们开始动手搭建一个完整的cas服务实现2个web之间的单点登录。
我们这里为了感受完整的简单的CAS搭建流程,这里有两个地方做了简化:
我们在上一篇已经学习了CAS的认证方式支持很多种,可以是xml,可以是LADP服务,可以是数据库,我们这里因为是测试,所以先使用最简单的认证方式,也就是cas原生提供的测试用的一种方式,帐号密码是写死的。
我们在看网上很多CAS搭建的教程中会看到很多都有配置导入导入证书这个步骤,很繁琐而且容易失败或者出问题。
测试环境中自己用JDK自带的keytool工具生成证书。
如果以后真正在产品环境中使用肯定要去证书提供商去购买,证书认证一般都是由VeriSign认证,
中文官方网站: http://www.verisign.com/cn/。
也可以申请免费的StartSSL CA证书: StartSSL(公司名:StartCom)也是一家CA机构,它的根证书很久之前就被一些具有开源背景的浏览器支持(Firefox浏览器、谷歌Chrome浏览器、苹果Safari浏览器等)。
申请地址:http://www.startssl.com
申请方法参考: http://www.linuxidc.com/Linux/2011-11/47478.htm
而且不是官方付费购买的证书权限的话,浏览器还会报证书过期等等。
CAS默认使用的是HTTPS协议,如果对安全要求不高,可使用HTTP协议。
所以不一定需要配置证书,我们后面会讲到启用https时证书怎么配置。
但是这里先使用http协议,可以使我们的搭建流程更简便。
我们在cas的github项目中可以看到版本的发布情况,我们可以自己根据特性来选择版本。
https://github.com/apereo/cas/releases
点击DOCS然后查看Getting Started中的Installation Requirements可以看到需要哪些支持。
原则上越新的稳定版本越好,但是看到5.0版本以上基本都需要jdk1.8以上的支持,而且需要gradle构建工具来进行编译,4.1.11则需要maven3.3版本进行编译。
因为新版本的源码部署打包稍微麻烦一些,我们独立出来讲解在
单点登录(三)-----实战-----cas server 源码下载和部署
官网中4.0.0版本是有发布直接可用的war包版本的,我们直接使用4.0.0作为例子。
所以我选择了 CAS v4.0.0版本。
https://github.com/apereo/cas/releases
在下载页面找到4.0.0后选择 release.zip下载(只有4.0.0有这个选项,其他版本都只有源码):
我们把下载好的release.zip解压出来得到cas server 4.0.0的文件夹,文件夹中有module文件夹里面有可用的war包。
注意只有4.0.0版本的有module文件夹和可用war包,其他版本的源码zip解压出来是没有的,需要自己编译打包。
ps:!!!!注意是cas-server-webapp-4.0.0.war包,别用错cas-management-webapp-4.0.0.war了,否则后面会出现页面重定向错误http://localhost:9000/cas/login?service=http%3A%2F%2Flocalhost%3A9000%2Fcas-management%2Fj_spring_cas_security_check。
然后我们把war包复制到tomcat的webapp文件夹,为了方便访问,我们先把war包名称修改成cas.war。运行tomcat即可解压出cas-server项目。
这样我们就能访问cas-server项目了。
如果tomcat的端口不是用的8080的话 还需要在解压出来的cas工程中修改一下配置文件cas.properties中的server.name,如图:
我这里把它修改成http://localhost:9000
然后重启tomcat
然后访问的时候就能使用
http://localhost:9000/cas/login
访问。
这里的9000端口是我的tomcat设置的端口,读者自己对应自己的端口。
然后我们尝试使用http://localhost:9000/cas/login访问。
出现如下页面则部署成功:
但是我们注意到这里有一句提醒:
You are currently accessing CAS over a non-secure connection. Single Sign On WILL NOT WORK. In order to have single sign on work, you MUST log in over HTTPS.
意思是我们不是通过https协议连接的。
cas默认是采用https模式的,我们没有配置证书,所以要么配置证书,要么取消https的过滤,让http协议也能访问。
我们这里取消https的配置,让http也能访问。
需要修改三个地方的配置(针对4.0.0版本,其他版本的话第一处必改,其他的看看还有没有带有cookie的文件名)
我们在tomcat的webapp中找到 cas/WEB-INF/deployerConfigContext.xml
里面有一句
这里需要增加参数p:requireSecure="false",requireSecure属性意思为是否需要安全验证,即HTTPS,false为不采用。修改后为:
我们在tomcat的webapp中找到cas/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml
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为无生命周期,即只在当前打开的IE窗口有效,IE关闭或重新打开其它窗口,仍会要求验证。可以根据需要修改为大于0的数字,比如3600等,意思是在3600秒内,打开任意IE窗口,都不需要验证。
这里把 cookieSecure修改为false就行了
我们在tomcat的webapp中找到cas/WEB-INF/spring-configuration/warnCookieGenerator.xml
里面有
p:cookieMaxAge="-1"
p:cookieName="CASPRIVACY"
p:cookiePath="/cas" />
参数p:cookieSecure="true",同理为HTTPS验证相关,TRUE为采用HTTPS验证,FALSE为不采用https验证。
这里把 cookieSecure修改为false就行了。
三个地方都修改好后我们就可以启动tomcat了,这时候https的方式已经取消,可以使用http的方式访问了。
ps:我们这里还没配置cas 客户端也就是我们的web应用,但是记得把客户端filter中的http链接也修改成http即可。
PS:配置完http方式访问之后页面上的 提示还是存在的,如果我们之后会对登录界面样式完全改版,所以可以不用管它。如果还是需要把它去掉的话,cas统一认证的登陆页面位于:cas目录/WEB-INF/view/jsp/default 文件夹里,其中ui/casLoginView.jsp为登陆页面。我们找到这段代码删掉即可。
You are currently accessing CAS over a non-secure connection. Single Sign On WILL NOT WORK. In order to have single sign on work, you MUST log in over HTTPS.
Non-secure Connection
我们之前说过cas server对用户密码的认证是支持很多种方式的,我们可以进行配置。
4.0.0版本的cas是在deployerConfigContext.xml文件中进行配置的。我们找到这个部分。
AcceptUsersAuthenticationHandler 是普通认证类型,也就是直接对照帐号密码。
可以看到测试版本的帐号是casuser密码是 Mellon,是写死的。我们就用这个帐号密码进行登录即可,或者修改成你喜欢的帐号密码再启动tomcat。
登录后显示登录成功说明我们的cas server部署成功了。
接着我们就要开始部署cas client了,也就是把我们的web项目于cas server关联起来。
我们在官网下载到的cas client项目不是web 项目的形式(不是war包),不能直接使用,它只是一个jar包,需要融合到我们的web项目,使web项目变得支持cas服务。
CAS client是部署在应用端的,因为通常单点登陆都会涉及到对已有系统的改造。所以,client端的侵入性就变的很重要。侵入性越小,越容易部署和测试。CAS框架的优点之一就在于它的client端对应用系统的侵入性比较小。对于Java的Web项目来说,你只需要在web.xml里面添加一个filter,拷贝CAS client的jar包到应用系统,然后改造登陆认证过程即可。如果CAS server用的是Https,那就还需要将证书导入到JVM的可信证书域中,通常是($JAVA_HOME/lib/security/cacerts)。
生成环境中是把已有的web项目进行改造,我们这里为了简化,可以新建一个web项目。
我在myeclipse中新建两个maven类型的web项目如下(分别命名为cas-client1和cas-client2):
这里拷贝的cas client的jar包也就是官网提供的cas client项目。下载地址:
https://github.com/apereo/java-cas-client
下载到的是源代码,需要把cas-client-core打包成jar包才能使用。
将cas-client-core-3.2.1.jar放入应用WEB-INF/lib下即可。
如果我们的web项目是maven项目的话就方便很多,直接在pom.xml文件添加以下引用即可:
org.jasig.cas.client
cas-client-core
${java.cas.client.version}
我们在tags中可以看到有哪些产品号
所以我们这里的会使用3.4.1版本。pom.xml中添加的代码为:
org.jasig.cas.client
cas-client-core
3.4.1
正式生产环境中,cas client配置cas server的地址时如果是使用https验证的话不能使用ip的,只能用域名,域名需要与生成证书时填写的域名一样,如果是http模式验证的话,则cas server的地址可以使用ip。
我们这里是做测试,所以可以在cas client所在的系统上修改hosts文件做域名映射。
否则的话会报各种错误。
win 10的hosts文件在 C:\WINDOWS\system32\drivers\etc
编辑新增127.0.0.1 casserver
保存
如果保存不了的话是权限问题,对着hosts文件右键属性安全里去设置即可。
验证一下 运行tomcat 我们的cas server能不能用域名访问,之前的访问地址是
http://localhost:9000/cas/login
现在尝试用
http://casserver:9000/cas/login 访问。
访问成功,域名映射就设置好了。
包引入之后我们就可以使用cas的服务了,主要是要配置一下过滤器。
cas有几个重要的filter:
org.jasig.cas.client.authentication.AuthenticationFilter (负责客户端认证)
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter (按照CAS2体系结构校验Ticket)
org.jasig.cas.client.util.HttpServletRequestWrapperFilter (包装request.getRemoteUser()数据)
org.jasig.cas.client.util.AssertionHolder(来获取用户的登录名)
web.xml中需要增加的代码格式为(还需要根据我们的环境进行参数调整):
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
CAS Single Sign Out Filter
org.jasig.cas.client.session.SingleSignOutFilter
casServerUrlPrefix
http://casserver:9000/cas/
CAS Single Sign Out Filter
/*
CASFilter
org.jasig.cas.client.authentication.AuthenticationFilter
casServerLoginUrl
http://casserver:9000/cas/login
serverName
http://localhost:9000
useSession
true
redirectAfterValidation
true
CASFilter
/*
CAS Validation Filter
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
casServerUrlPrefix
http://casserver:9000/cas/
serverName
http://localhost:9000
CAS Validation Filter
/*
CAS HttpServletRequest Wrapper Filter
org.jasig.cas.client.util.HttpServletRequestWrapperFilter
CAS HttpServletRequest Wrapper Filter
/*
CAS Assertion Thread Local Filter
org.jasig.cas.client.util.AssertionThreadLocalFilter
CAS Assertion Thread Local Filter
/*
https://github.com/apereo/java-cas-client
http://blog.csdn.net/zzq900503/article/details/54646828
ps:
域名映射小节已经讲了,这里再强调一次。
如果是没有取消https认证的话casServerLoginUrl和casServerUrlPrefix必须使用域名,且域名要和证书中的“名字与姓氏”完全相同,没有域名的可以配置本地hosts做映射 。我们这里已经去取消了https的协议,让http也能访问所以不需要与证书对应,但是也需要设置一下域名映射。
serverName:是cas-client本项目的ip+port,我们这里cas client项目也放在tomcat 9000中,所以端口也是一样的。
最终的web.xml为:
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
index.jsp
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
CAS Single Sign Out Filter
org.jasig.cas.client.session.SingleSignOutFilter
casServerUrlPrefix
http://casserver:9000/cas/
CAS Single Sign Out Filter
/*
CASFilter
org.jasig.cas.client.authentication.AuthenticationFilter
casServerLoginUrl
http://casserver:9000/cas/login
serverName
http://localhost:9000
useSession
true
redirectAfterValidation
true
CASFilter
/*
CAS Validation Filter
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
casServerUrlPrefix
http://casserver:9000/cas/
serverName
http://localhost:9000
CAS Validation Filter
/*
CAS HttpServletRequest Wrapper Filter
org.jasig.cas.client.util.HttpServletRequestWrapperFilter
CAS HttpServletRequest Wrapper Filter
/*
CAS Assertion Thread Local Filter
org.jasig.cas.client.util.AssertionThreadLocalFilter
CAS Assertion Thread Local Filter
/*
到这里我们的两个client也部署好了,现在可以测试sso是否能够实现了。
我们先分别把cas-client1的index.jsp和cas-client2的index.jsp页面修改一下,使它们能够区分出来。
我这里改的是body的内容,分别改成cas-client1和cas-client2。
然后把cas-client1和cas-client2两个项目都加入到tomcat 9000的webapp中 运行tomcat。
启动tomcat确认不报错之后我们访问
localhost:9000/cas-client2
发现它成功被拦截了。
跳转到了
http://casserver:9000/cas/login?service=http%3A%2F%2Flocalhost%3A9000%2Fcas-client2%2F
然后我们再访问
localhost:9000/cas-client1
则是被拦截跳转到了
http://casserver:9000/cas/login?service=http%3A%2F%2Flocalhost%3A9000%2Fcas-client1%2F
然后我们输入帐号密码。
casuser和Mellon
登录成功后调整到了cas-client1的首页
然后我们再直接访问cas-client2的项目地址
localhost:9000/cas-client2
发现不需要再输入帐号密码,也可以登录了。
到这里说明我们的SSO单点登录已经部署验证成功了。
后续我们会进行一些优化和调优等等。