原文地址:http://blog.csdn.net/puma_dong/article/details/11564309
版权声明:本文为博主原创文章,未经博主允许不得转载。
cas官网文档访问地址:https://wiki.jasig.org/display/CASUM/Home。
我下载的是:3.5.2版本。我配置好的cas界面如下:
界面一:
界面二:
下载链接:
已经搞好的Java客户端及服务器端(MySQL)配置下载:http://pan.baidu.com/s/11MRPr ,两个war包,1个jar包:
cas.war,是配置好的cas服务器端:http://192.168.1.10:8080/casclient 。
casclient.war,是cas客户端示例,所谓cas客户端,就是指使用cas进行单点登录的系统: http://192.168.1.10:8080/cas/login。
cas-client-core-3.2.1-SNAPSHOT.jar:是我在版本3.2.1源码基础上进行修改过的,目的是登录成功后,自动跳转到前一页。
要修改cas.war包中deployerConfigContext.xml里面的数据库连接串及密码查询SQL,jasig日志文件的位置:tomcat所在磁盘:/data/applogs/jasig/目录下,可以通过修改WEB-INFO/class/log4j.xml进行配置。
需要的MySQL数据库privilege建表及数据初始化脚本:create_privilege.sql
使用这个数据库,默认的登录帐户密码:root/root
最新代码Git地址:
cas -server-3.5.2:https://github.com/pumadong/cas-server-3.5.2
cas-client-3.2.1:https://github.com/pumadong/cas-client-3.2.1
Jasig cas服务器端配置:
Jasig cas的功能是认证(单点登录,SSO,Single Sign On),关于系统的授权,由于各个系统可能都不太一样,各个系统自行负责为宜。
Jasig cas的配置非常简单,从官网下载的源码包中,有个module目录,里面有制作好的war包,可以直接使用,当然也可以自行使用maven打包,命令如下:
mvn clean package -Dmaven.test.skip=true -U
把war包改名为cas.war,放到tomcat的webapps目录下,就可以使用了,默认使用的是登陆验证类是测试用的,只要用户名、密码一直就算登陆成功,为了在生产环境使用,我们改为使用MySql数据库验证,步骤如下:
1、简单起见,我们不使用https认证,做如下更改:
WEB-INF\spring-configuration目录下ticketGrantingTicketCookieGenerator.xml和warnCookieGenerator.xml,把p:cookieSecure="true"改为p:cookieSecure="false"
WEB-INF目录下deployerConfigContext.xml中,在如下节点中,增加p:requireSecure="false",
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" p:requireSecure="false" />
2、使用MySql验证
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" p:requireSecure="false" />
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="select password from p_user where username=?" />
<property name="passwordEncoder" ref="passwordEncoderBean"/>
</bean>
</list>
</property>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8</value>
</property>
<property name="username"><value>root</value></property>
<property name="password"><value>root</value></property>
</bean>
<bean id="passwordEncoderBean" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">
<constructor-arg value="MD5" />
</bean>
注意:
同时,需要把cas-server-support-jdbc-3.5.2.jar包放在cas.wab包的WEB-INF目录下,把mysql-connector-java-5.1.24-bin.jar放入Tomcat的WEB-INF/lib目录里。
3、退出时跳转到service页
修改src\main\webapp\WEB-INF\cas-servlet.xml里的logoutController
增加p:followServiceRedirects="true"使支持logout输入service参数为跳转路径。
4、增加免登陆(Remember Me)功能
CAS增加免登陆(Remember Me)功能:
https://wiki.jasig.org/display/CASUM/Remember+Me
http://blog.163.com/wunan_23/blog/static/19556232020111127714418/
Jasig cas客户端配置
1、pom.xml配置
<!-- CAS Client -->
<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.1.10</version>
</dependency>
如果不使用maven的话,直接下载jar包即可。
2、web.xml配置
<!-- ======================== 单点登录开始 ======================== -->
<!-- 说明:这种客户端的配置方式是不需要Spring支持的 -->
<!-- 参考资料:http://blog.csdn.net/yaoweijq/article/details/6003187 -->
<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>CAS Authentication Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://localhost:8080/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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:8080/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation 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>
<!-- ======================== 单点登录结束 ======================== -->
3、单点退出
单点退出的原理,可以总结为一句话:
A客户端退出,调用cas服务器的logout,cas server会向所有相关的接入CAS的系统发送消息,这些接入CAS的系统监听到消息后,触发session失效。
注意:我们的接入CAS的系统必须是cas服务器可以访问到的,如果我们使用:http://localhost:8080/picture的形式访问站点,则是无法实现单点登出的,因为cas服务器访问不到我们的localhost,必须改成:http://ip地址:8080/picture的形式,让CAS可以访问到我们的系统。
参考:
http://www.blogjava.net/xmatthew/archive/2008/07/09/213808.html
http://blog.csdn.net/yuwenruli/article/details/6607669
更改单点登录界面
WEB-INF\view\jsp\default\ui
登陆界面:casLoginView.jsp
登陆成功:casGenericSuccess.jsp
登出界面:casLogoutView.jsp
cas是支持国际化的,关于页面中显示的提示信息的存储位置class/*.properties,默认是en,为了让比较简单的中文化,我把en做了个备份,然后把zh_CN拷贝成en。
在properties文件中, 对于非英文的字符,采用16进制存储,关于unicode字符和16进制字符的转换,提供如下两个函数:
- //把中文字符串转换为十六进制Unicode编码字符串
- public static String stringToUnicode(String s) {
- String str = "";
- for (int i = 0; i < s.length(); i++) {
- int ch = (int) s.charAt(i);
- if (ch > 255)
- str += "\\u" + Integer.toHexString(ch);
- else
- str += "\\" + Integer.toHexString(ch);
- }
- return str;
- }
- //把十六进制Unicode编码字符串转换为中文字符串
- public static String unicodeToString(String str) {
- Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
- Matcher matcher = pattern.matcher(str);
- char ch;
- while (matcher.find()) {
- ch = (char) Integer.parseInt(matcher.group(2), 16);
- str = str.replace(matcher.group(1), ch + "");
- }
- return str;
- }
也可以更改cas-servlet.xml文件中关于本地化的配置,把:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/> 修改为:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.FixedLocaleResolver"/>
这个本地化解析器返回一个固定的本地化信息。默认值为当前JVM的locale。
另外,我在修改一个CAS界面时,运行过程中每次刷新页面都报一个警告:WARN:oejh.HttpGenerator:Ignoring extra content,并且点击页面的submit按钮,大于在第3或者第5次的时候,页面就reload了,后来用排除法(逐渐缩小代码范围)找出问题,我的新界面的login_soft.css中,有关于图片的css:background: url(../../img/bg-white-lock.png) repeat; 但是对应的目录下没有相应图片,导致了如上的两个问题。把图片都拷贝到相应目录后,问题解决。为什么会这样,原因尚不明,估计与CAS的WebFlow相关代码有关,不深入继续研究了
关于log4j.xml
logger的默认additivity值是true,代表日志继续抛出到root进行处理,此时会被root里面所有appender处理;
logger设置additivity的值为false,代表日志被此节点的appender吃掉,不继续抛出;
root里面的<level value="ERROR" />只对空的logger节点才生效,比如:
<logger name="com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager" additivity="true" />
关于源码
cas-server-webapp项目里面,测试下面的很多xml都是格式不正确(其实可以直接在Eclipse里面把Validate关掉),报如下错误:
The markup in the document following the root element must be well-formed.
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-support-jdbc</artifactId>
<version>${project.version}</version>
</dependency>
- //修改类:org.jasig.cas.client.util.AbstractCasFilter的constructServiceUrl,修改后内容如下:
- //return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName, this.artifactParameterName, this.encodeServiceUrl);
- String currentPage = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
- + request.getRequestURI()
- + (CommonUtils.isNotBlank(request.getQueryString()) ? ("?"+request.getQueryString()) : "");
- String ticket = request.getParameter("ticket");
- //http://192.168.1.200:8080/cas/serviceValidate?ticket=ST-74-bJsAKJivCfkABMWLgViu-cas01.example.org&service=http%3A%2F%2Flocalhost%3A8080%2Fauthority%2Fcontroller%2Fmain.do%3Fticket%3DST-74-bJsAKJivCfkABMWLgViu-cas01.example.org
- //去掉参数中所有ticket相关的部分
- currentPage = currentPage.replace("%3Fticket%3D"+ticket, "");
- currentPage = currentPage.replace("&ticket="+ticket, "");
- currentPage = currentPage.replace("?ticket="+ticket, "");
- currentPage = currentPage.replace("&service=", "?service");
- return currentPage;
- //或者修改类:org.jasig.cas.client.util.CommonUtils的constructServiceUrl,修改后被替换后的内容如下:
- if (CommonUtils.isBlank(serverName)) {
- buffer.append(request.getRequestURL());
- }else{
- if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
- buffer.append(request.isSecure() ? "https://" : "http://");
- }else{
- buffer.append(serverName);
- }
- buffer.append(request.getRequestURI());
- }
工作原理
参考文章:
http://www.docin.com/p-370942269.html
http://blog.sina.com.cn/s/blog_56d8ea900100l44r.html
http://www.doc88.com/p-183734738161.html
http://wenku.baidu.com/view/5c64b1f19e31433239689318.html
http://www.blogjava.net/tufanshu/archive/2011/01/21/343290.html