CAS Server 4.0二次开发说明文档
更新时间:2024-05-12 09:45:01 阅读量: 综合文库 文档下载
- casetify推荐度:
- 相关推荐
CAS Server4.0二次开发说明文档
1. 环境搭建...................................................................................................................................... 2 2. 拓展后最终目录结构 .................................................................................................................. 7 3. 修改CAS Server支持HTTP协议 ................................................................................................ 8 4. 修改CAS服务器端登录认证方式为数据库认证 ...................................................................... 9
4.1. 在pom中添加如下的依赖 ............................................................................................. 9 4.2. 创建ValidUserQueryDBAuthenticationHandler ............................................................ 10 4.3. 修改deployerConfigContext.xml ................................................................................... 10 5. 登录连续错误三次以上出现验证码校验 ................................................................................ 11
5.1. 添加kaptcha验证码依赖库.......................................................................................... 11 5.2. 配置web.xml ................................................................................................................. 11 5.3. UsernamePasswordCaptchaCredentia ............................................................................ 12 5.4. 修改cas登录页,添加验证码字段 ............................................................................. 12 5.5. 添加验证码校验 ............................................................................................................ 13 5.6. 自定义异常处理Handler 统计错误次数..................................................................... 15 5.7. 修改配置cas-servlet.xml ............................................................................................... 16 5.8. 修改配置login-webflow.xml .......................................................................................... 16 6. CAS服务器端返回多个属性字段.............................................................................................. 17
6.1. 创建MultipleAttributeUserDao模拟用户自定义属性 ................................................ 17 6.2. 修改deployerConfigContext.xml ................................................................................... 18 6.3. 修改casServiceValidationSuccess.jsp ............................................................................ 18 7. CAS Server集群部署时Ticket同步 ........................................................................................... 20
7.1. 添加redis依赖 .............................................................................................................. 20 7.2. 创建RedisTicketRegistry ................................................................................................ 21 7.3. 创建TicketRedisTemplate .............................................................................................. 21 7.4. 修改ticketRegistry.xml ................................................................................................... 22 7.5. 修改web.xml ................................................................................................................. 23 8. CAS Server登录页定制 .............................................................................................................. 23
8.1. 拷贝资源文件 ................................................................................................................ 23 8.2. 修改casLoginView.jsp .................................................................................................... 23 8.3. 基于theme方式 ............................................................................................................ 24 9. 修改CAS Server为移动端设备提供REST登录服务 .............................................................. 24
9.1. 添加依赖 ........................................................................................................................ 24 9.2. 修改webx.xml ................................................................................................................ 26 9.3. 请求票据授权 ................................................................................................................ 26 9.4. 请求服务授权 ................................................................................................................ 27 9.5. Java Client测试 ............................................................................................................... 28
在生产环境中,官方提供的CAS Server功能远远不能满足我们的需求。这个时候我们就需要基于源码进行二次开发,以满足我们的线上使用。这里主要是基于CAS服务器端。本文档主要描述目前在CAS Server 4.0版本基础上做了哪些改进。
1. 环境搭建
这里为了方便起见采用maven overlays特性(通路径下的同名文件会使用最新的资源文件替换已有war目录中下的资源文件)搭建,因此这里不用将cas-server-webapp模块的所有源码导入到工程里,只需将需要修改的文件按源码里面的目录层次结构排列,最终编译构建打包时会自动添加新特性或替换原有文件,这是一件很方便的事,修改和添加了哪些文件一目了然。
以下列出了本文档所涉及到所有拓展功能及最终编译打包所需的maven依赖。 pom.xml
2. 拓展后最终目录结构
3. 修改CAS Server支持HTTP协议
修改src\\main\\webapp\\WEB-INF\\spring-configuration\\ticketGrantingTicketCookieGenerator.xml文件
修改src\\main\\webapp\\WEB-INF\\spring-configuration\\warnCookieGenerator.xml文件 4. 修改CAS服务器端登录认证方式为数据库认证
Cas Server默认提供简单用户密码认证即(casuser/Mellon,该部分内容在src\\main\\webapp\\WEB-INF\\deployerConfigContext.xml文件中可以看到。),显然这不能满足我们的线上环境。在此我们需要修改使其支持基于数据库的用户名密码校验。要想使用数据库校验,需要为cas server提供相应的jdbc依赖。
4.1. 在pom中添加如下的依赖
4.2. 创建ValidUserQueryDBAuthenticationHandler
在src/main/java目录下创建org.jasig.cas.adaptors.jdbc包,在该包下创建ValidUserQueryDBAuthenticationHandler.java文件。因内容较多,这里不再列出,具体请查看源码
4.3. 修改deployerConfigContext.xml
为了防止cas server被恶意登录及防暴力登录。这里采用验证码校验。为了良好的用户体验,设定当连续登录错误次数达到3次及以上需验证验证码登录。 这里使用开源的kaptcha来做验证码 5.1. 添加kaptcha验证码依赖库 该库并没有上传到maven中央仓库,因此我们需要自行发布到私服,或者使用上面的scope结合systemPath引用,使用这种方式时,在打包的时候不会打到war包里面,因此为了方便起见建议下载下来自行上传到maven私服或安装到本地仓库。 使用下面的命令即可安装到本地仓库 mvn install:install-file -DgroupId=com.google.code.kaptcha -DartifactId=kaptcha -Dversion=2.3.2 -Dfile=E:\\cas-4.0.0\\cas-server-webapp\\lib\\kaptcha-2.3.2.jar -Dpackaging=jar -DgeneratePom=true 5.2. 配置web.xml 在src\\main\\webapp\\WEB-INF\\web.xml中添加如下内容 创建UsernamePasswordCaptchaCredential继org.jasig.cas.authentication.RememberMeUsernamePasswordCredential 主要是拓展了一个验证字段captcha. @NotNull @Size(min = 1, message = \private String captcha; 承 自 5.4. 修改cas登录页,添加验证码字段 修改src\\main\\webapp\\WEB-INF\\view\\jsp\\default\%ui\\casLoginView.jsp添加验证码及记住密码字段
5.5. 添加验证码校验
在org.jasig.cas.web.flow包下创建CaptchaVaditeAuthenticationViaFormAction并继承自AuthenticationViaFormAction
其具体内容如下: package org.jasig.cas.web.flow; import org.jasig.cas.authentication.Credential; import org.jasig.cas.authentication.UsernamePasswordCaptchaCredential; import org.jasig.cas.web.support.WebUtils; import org.springframework.binding.message.MessageBuilder; import org.springframework.binding.message.MessageContext; import org.springframework.util.StringUtils; import org.springframework.webflow.execution.RequestContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * 验证码校验 * Created by fengjing on 2016/4/27. */ public class CaptchaVaditeAuthenticationViaFormAction extends AuthenticationViaFormAction { private static final String CAPTCHA_REQUIRED_MSG = \验证码必填 private static final String CAPTCHA_ERROR_MSG = \验证码不正确 public final String validate(final RequestContext context, final Credential credentials, final MessageContext messageContext) throws Exception { final HttpServletRequest request = WebUtils.getHttpServletRequest(context); HttpSession session = request.getSession(); // 用户输入错误次数累计,次数大于3次则显示验证码 int count; try { count = (Integer) context.getFlowScope().get(\ } catch (Exception e) { count = 0; } // 获取用户名密码 String username = request.getParameter(\ String password = request.getParameter(\ // 用户名非空验证 if (StringUtils.isEmpty(username)) { populateErrorsInstance(\ count++; context.getFlowScope().put(\ return \ } // 密码非空验证 if (StringUtils.isEmpty(password)) { populateErrorsInstance(\ count++; context.getFlowScope().put(\ return \ } // 验证码判断 String showCaptcha = request.getParameter(\ // 判断验证码是否显示 if (StringUtils.hasText(showCaptcha)) { // 从session中获取验证码 String authcode = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); session.removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); UsernamePasswordCaptchaCredential upc = (UsernamePasswordCaptchaCredential) credentials; // 获取用户输入的验证码 String submitAuthcode = upc.getCaptcha(); // 验证码非空判断 if (!StringUtils.hasText(submitAuthcode) || !StringUtils.hasText(authcode)) { populateErrorsInstance(CAPTCHA_REQUIRED_MSG, messageContext); count++; context.getFlowScope().put(\ return \ } // 验证码正确性判断 if (submitAuthcode.equals(authcode)) { return \ } else { populateErrorsInstance(CAPTCHA_ERROR_MSG, messageContext); count++; context.getFlowScope().put(\ return \ } } return \ } private void populateErrorsInstance(final String errorCode, final MessageContext messageContext) { try { messageContext.addMessage(new MessageBuilder().error().code(errorCode).defaultText(errorCode).build()); } catch (final Exception fe) { logger.error(fe.getMessage(), fe); } } } 5.6. 自定义异常处理Handler 统计错误次数
在org.jasig.cas.web.flow包下创建MyAuthenticationExceptionHandler。重写handle方法,着重在这里处理计算错误次数 public String handle(final RequestContext context, final AuthenticationException e, final MessageContext messageContext) { int count; try { count = (Integer) context.getFlowScope().get(\} catch (Exception ex) { count = 0; } if (e != null) { for (final Class extends Exception> kind : this.errors) { for (final Class extends Exception> handlerError : e.getHandlerErrors().values()) { if (handlerError != null && handlerError.equals(kind)) { final String messageCode = this.messageBundlePrefix + handlerError.getSimpleName(); messageContext.addMessage(new MessageBuilder().error().code(messageCode).build());
count++; context.getFlowScope().put(\ return handlerError.getSimpleName(); } } } } final String messageCode = this.messageBundlePrefix + UNKNOWN; logger.trace(\by default...\messageContext.addMessage(new MessageBuilder().error().code(messageCode).build()); count++; context.getFlowScope().put(\return UNKNOWN; } 5.7. 修改配置cas-servlet.xml
修改src\\main\\webapp\\WEB-INF\\cas-servlet.xml 的 CaptchaVaditeAuthenticationViaFormAction 及 5.8. 修改配置login-webflow.xml 修改src\\main\\webapp\\WEB-INF\\login-webflow.xml文件,该文件采用了spring-web-flow.在这里定义描述了整个cas server的登录校验认证流程。接下来,需要在登录属性表单中添加验证码字段及添加修改有关涉及到验证码校验的流程 替换原来的credential配置为UsernamePasswordCaptchaCredential 通常情况下,cas server认证成功后返回的属性字段很少,但在很多场合下登录后需要获取到许多字段属性。这时候我们就需要个性化来定制cas server返回的字段属性了。这里为了方便演示期间,创建了一个MultipleAttributeUserDao类,并重写了IPersonAttributes方法,在这里模拟了一些字段属性。在生产环境时,可将该部分代码替换,根据业务需求换成从数据库中查询的业务逻辑代码。 6.1. 创建MultipleAttributeUserDao模拟用户自定义属性 package org.jasig.services.persondir.support; import org.jasig.services.persondir.IPersonAttributes; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 扩展用户自定义属性 * Created by Administrator on 2016/4/30 0030. */ public class MultipleAttributeUserDao extends StubPersonAttributeDao { @Override public IPersonAttributes getPerson(String uid) { Map 修改src\\main\\webapp\\WEB-INF\\deployerConfigContext.xml文件,添加配置我们自定义的MultipleAttributeUserDao 6.3. 修改casServiceValidationSuccess.jsp 至此为了能获取到我们的自定义属性还不需要修改src\\main\\webapp\\WEB-INF\\view\\jsp\\protocol\\2.0\\casServiceValidationSuccess.jsp和src\\main\\webapp\\WEB-INF\\view\\jsp\\protocol\\3.0\\casServiceValidationSuccess.jsp文件。添加获取用户自定义属性的代码块。 src\\main\\webapp\\WEB-INF\\view\\jsp\\protocol\\2.0\\casServiceValidationSuccess.jsp <%-- <%@ page session=\<%@ taglib prefix=\<%@ taglib uri=\ 当cas server被正式用在生产环境时,她需要支撑各个应用系统的登录服务。而cas server只进行一处部署时,这里就存在一个单点故障的问题。一旦出现该问题,就会导致各个应用系统无法正常登录。次问题是极为严重的。因此我们在线上使用的时候就需要将cas server进行集群部署,可cas server相对于其他web应用集群部署有所不同。我们知道cas server的用户身份校验是基于cas ticket的。Cas默认的ticket管理策略是不具备集群部署时ticket同步的。这里就需要我们自行拓展,以达到集群部署时ticket也能同步。 7.1. 添加redis依赖 在这里我们使用redis缓存策略来同步管理cas ticket。因此需要添加redis依赖 commons-pool2 在org.jasig.cas.ticket.registry包下创建RedisTicketRegistry,提供一些基于redis对Ticket的增删改查操作。这里涉及内容较多,具体不一一列出,请查看源码。 7.3. 创建TicketRedisTemplate 在org.jasig.cas.ticket.registry包下创建TicketRedisTemplate,用来管理redis的序列化策略 package org.jasig.cas.ticket.registry; import org.jasig.cas.ticket.Ticket; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * CasServer集群环境下使用Redis缓存Ticket * Created by fengjing on 2016/4/27. */ public class TicketRedisTemplate extends RedisTemplate 7.4. 修改ticketRegistry.xml 修改src\\main\\webapp\\WEB-INF\\spring-configuration\\ticketRegistry.xml文件,配置我们自定义的RedisTicketRegistry Configuration for the default TicketRegistry which stores the tickets in-memory and cleans them out as specified intervals. 这里关于redis的配置放在了cas.properties文件中。 7.5. 修改web.xml 最后一步,记得在web.xml中添加 关于tomcat集群部署及整合nginx或apache负载均衡session同步的内容这里不做赘述,可参考我之前写的搭建配置文档。 使用Redis或Memcached实现Tomcat7+Nginx集群及Session共享 https://github.com/sxyx2008/tomcat7-nginx-redis-memcached-cluster Apache、Tomcat7集群session共享及负载均衡 https://github.com/sxyx2008/apache2-tomcat7-cluster 8. CAS Server登录页定制 这部分内容较为简单。 8.1. 拷贝资源文件 事先让美工设计一套登录页面。然后将css、image、js拷贝到src\\main\\webapp\\css src\\main\\webapp\\images src\\main\\webapp\\js目录下。 8.2. 修改casLoginView.jsp 修改src\\main\\webapp\\WEB-INF\\view\\jsp\\default\%ui\\casLoginView.jsp文件,直接拷贝原来的spring form表单组件替换现有模板对应的表单元素。注意其name属性的值。 下图为自定义的cas server登录页 8.3. 基于theme方式 以上是一种快捷便利的修改方式,官方也提供基于theme的修改方案。 按原有目录结构拷贝src\\main\\webapp\\WEB-INF\\view\\jsp\\default一份并为其重命名。该名称即为theme name。然后修改src\\main\\webapp\\WEB-INF\\cas.properties进行如下配置 cas.viewResolver.basename=default_views # cas定制登录页主题lamppa 主题文件路径src\\main\\webapp\\WEB-INF\\view\\jsp\\lamppa #cas.themeResolver.defaultThemeName=cas-theme-lamppa #cas.viewResolver.basename=lamppa_views 接着修改对应的文件即可。 9. 修改CAS Server为移动端设备提供REST登录服务 http://apereo.github.io/cas/4.0.x/protocol/REST-Protocol.html Cas Server主要为web应用提供单点登录解决方案。可在现实中有时候我们也需要为移动端设备提供登录服务。这时候难道还是去请求cas server的统一登录页吗?这有点太low了。Cas官方为我们提供了cas rest风格的登录支持。要使用该功能,就必须得添加相应的依赖。 9.1. 添加依赖 在web.xml中添加如下配置 POST http://192.168.0.99:9000/cas/v1/tickets username=adminoue&password=4009696109 发送一个POST请求到/cas/v1/tickets,传递请求参数为username=adminoue&password=4009696109。请求成功后会返回http://192.168.0.99:9000/cas/v1/tickets/TGT-7-U71jox1ykWosLwQQSpcc5g47jdKul9ccgjgxgIchl64rSTpa1K-localhost。 其TGT-7-U71jox1ykWosLwQQSpcc5g47jdKul9ccgjgxgIchl64rSTpa1K-localhost为服务器端返回的请求票根。下文在请求服务的时候需携带该信息。 9.4. 请求服务授权 POST http://192.168.0.99:9000/cas/v1/tickets/TGT-7-U71jox1ykWosLwQQSpcc5g47jdKul9ccgjgxgIchl64rSTpa1K-localhost service=http://www.aimeizi.net即可,最终返回一串ST-4-3V9Fs9PbbcUZ5PiIJaR6-localhost表示登录成功。 这里需要携带上文请求后返回的请求票据,请求该票据并传递service=你的应用地址最终返回登录成功后的票据信息。 9.5. Java Client测试 这里使用commons-httpclient来模拟上述中的请求流程。 import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import java.io.IOException; import java.net.URLEncoder; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by Administrator on 2016/5/11 0011. */ public class Client { public static String getTicket(final String server, final String username, final String password, final String service) { notNull(server, \ notNull(username, \ notNull(password, \ notNull(service, \ return getServiceTicket(server, getTicketGrantingTicket(server, username, password), service); } /** * 取得ST * * @param server * @param ticketGrantingTicket * @param service */ private static String getServiceTicket(final String server, final String ticketGrantingTicket, final String service) { if (ticketGrantingTicket == null) return null; final HttpClient client = new HttpClient(); final PostMethod post = new PostMethod(server + \ post.setRequestBody(new NameValuePair[]{new NameValuePair(\ try { client.executeMethod(post); final String response = post.getResponseBodyAsString(); switch (post.getStatusCode()) { case 200: return response; default: warning(\server!\ info(\(1k): \+ response.substring(0, Math.min(1024, response.length()))); break; } } catch (final IOException e) { warning(e.getMessage()); } finally { post.releaseConnection(); } return null; } /** * @param server * @param username * @param password */ private static String getTicketGrantingTicket(final String server, final String username, final String password) { final HttpClient client = new HttpClient(); final PostMethod post = new PostMethod(server); post.setRequestBody(new NameValuePair[]{new NameValuePair(%username), new NameValuePair(\ try { client.executeMethod(post); final String response = post.getResponseBodyAsString(); info(\ switch (post.getStatusCode()) { case 201: { final Matcher matcher = Pattern.compile(\ if (matcher.matches()) return matcher.group(1); warning(\ info(\(1k): \+ response.substring(0, Math.min(1024, response.length()))); break; } default: warning(\server!\ info(\(1k): \+ response.substring(0, Math.min(1024, response.length()))); break; } } catch (final IOException e) { warning(e.getMessage()); } finally { post.releaseConnection(); } return null; } private static void ticketValidate(String serverValidate, String serviceTicket, String service) { notNull(serviceTicket, \ notNull(service, \ final HttpClient client = new HttpClient(); GetMethod post = null; try { post = new GetMethod(serverValidate + \+ \+ serviceTicket + \ client.executeMethod(post); final String response = post.getResponseBodyAsString(); info(response); switch (post.getStatusCode()) { case 200: { info(\成功取得用户数据\ } default: { } } } catch (Exception e) { warning(e.getMessage()); } finally { //释放资源 post.releaseConnection(); } } private static void notNull(final Object object, final String message) { if (object == null) throw new IllegalArgumentException(message); } public static void main(final String[] args) throws Exception { final String server = \ final String username = \ final String password = \ final String service = \ final String proxyValidate = \ ticketValidate(proxyValidate, getTicket(server, username, password, service), service); } private static void warning(String msg) { System.out.println(msg); } private static void info(String msg) { System.out.println(msg); } } 最终可以看到控制台请求到cas server服务器返回的数据。
正在阅读:
计价格(2002)10号文07-31
世纪公园美如画作文500字06-27
11精油香熏美容全攻略08-20
监理工作总结06-26
科赫雪花06-21
记住这几招 你也是命令提示符应用老司机04-16
私立学校项目建设可行性研究报告03-09
尼尔斯骑鹅旅行记课外阅读课指导教案03-15
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 说明
- 文档
- Server
- 开发
- CAS
- 4.0
- 浅谈农村小学体育教学现状以及对策
- 五凤古镇健康养老休闲旅游项目可行性研究报告9.10 - 图文
- ×抵押位于株洲市云龙示范区××的二宗划拨土地使用权价格评估(
- 《管理学》期末考试复习范围(简答OK)
- 高考英语必修3 Astronmy+the+science+of+the+stars(讲)-2018年
- 高一英语必修三必修四作文范文 - 按单元整理 2
- 保研个人陈述书
- 2010年度cdma网优技能比赛简答题 - 图文
- 国家安全网上法律知识竞赛参考答案
- 土的应力分布及计算
- 2012国培小学综合实践第一阶段课程作业
- 2013年某公司运输部门工作计划
- A管理模式(摘要)
- 大一《有机化学》题库
- 山东省滕州市夏庄镇17届高三生物一轮复习第二周自测题
- K3 BOS开发百问百答
- 按键可控计时电路的设计 - 图文
- 基于java的web服务器毕业论文
- 精装修工程施工工艺工法标准
- 大学本科工商管理毕业论文(1)