- 浏览: 320942 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (101)
- Oracle (7)
- Java (15)
- Hibernate (3)
- Struts2 (6)
- Linux (8)
- MySql (9)
- Ajax (4)
- Spring (4)
- Eclipse (5)
- Window (2)
- 架构 (1)
- JSP (2)
- 软件工程 (1)
- CSS (1)
- Tomcat (3)
- mysql 5 中文参考手册 (1)
- FreeMarker (1)
- Redis (3)
- cas (7)
- jquery (1)
- Maven (5)
- 测试 (1)
- GWT (3)
- 资料收集 (1)
- dis (0)
- Powerdesigner (1)
- JavaScript (1)
- log4j (1)
- rabbitmq (0)
最新评论
-
sdyjmc:
好人啊,内牛满面啊~~
Maven打包,并获取依赖的jar包&&设置main方法启动 -
wangxiang243:
不错很实用!
Maven打包,并获取依赖的jar包&&设置main方法启动 -
啦啦123:
...
java字符串格式化:String.format()方法的使用 -
plandu:
不错,我有个问题,怎么通过sigar获取CPU序列号、硬盘卷标 ...
java如何实现系统监控、系统信息收集、sigar开源API的学习(转) -
记录成长:
你用什么软件画的流程图呀?
让CAS支持客户端自定义登陆页面——原理篇
上篇《让CAS支持客户端自定义登陆页面——原理篇》讲述了一些修改的理论基础,这篇讲解如何对CAS服务器端进行修改。
修改需要基于几个基本原则:
- 不影响原有统一登陆界面功能
- 客户端应尽量保持简单
- 尽量保证原有功能的完整性和安全性
对于第三点,必须事先说明:将登陆页面放到客户端本身就是降低了CAS安全性,这意味着作为服务向外发布的CAS服务器中的用户密码有可能由于客户端的不安全性而导致泄露,整个CAS系统成为了一个“水桶形态”,整个CAS体系的安全性将取决于所有客户端中安全性最低的一个。这也是CAS官方一直不推荐的方式。
接下来我们讲解服务器端修改的详细过程:
首先,修改/WEB-INF/web.xml,为cas增加一个/remoteLogin的映射:
<servlet-mapping> <servlet-name>cas</servlet-name> <url-pattern>/remoteLogin</url-pattern><!--add servlet-mapping--> </servlet-mapping>
然后修改cas-servlet.xml文件,增加我们对/remoteLogin映射的处理,需要增加一个新流程:
<bean id="handlerMappingB" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/login">loginController</prop> <prop key="/remoteLogin">remoteController</prop><!--add --> </props> </property> <property name="interceptors"> <list> <ref bean="localeChangeInterceptor" /> </list> </property> </bean>
然后在cas-servlet.xml文件中添加我们上面所配置的remoteController的bean:
<!-- 增加远程控制者,允许以/remote请求启动remote控制流程 -->
<bean id="remoteLoginController" class="org.springframework.webflow.executor.mvc.FlowController" p:flowExecutor-ref="remoteLoginFlowExecutor" p:defaultFlowId="remoteLogin-webflow"> <property name="argumentHandler"> <bean class="org.springframework.webflow.executor.support.RequestParameterFlowExecutorArgumentHandler" p:flowExecutionKeyArgumentName="lt" p:defaultFlowId="remoteLogin-webflow" /> </property> </bean> <flow:executor id="remoteLoginFlowExecutor" registry-ref="remoteLoginFlowRegistry"> <flow:execution-attributes> <flow:alwaysRedirectOnPause value="false"/> </flow:execution-attributes> </flow:executor>
<!--update-->
<flow:registry id="remoteLoginFlowRegistry"> <flow:location path="/WEB-INF/remoteLogin-webflow.xml"/> </flow:registry>
可以看到上面将请求指向了webflow配置文件/WEB-INF/remoteLogin-webflow.xml文件,我们需要创建此文件并配置其成为我们所需的流程,以下是remoteLogin-webflow.xml全文:
<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd"> <start-state idref="remoteLogin"/> <!-- 远程登陆主要Action --> <action-state id="remoteLogin"> <action bean="remoteLoginAction" /> <transition on="error" to="remoteCallbackView" /> <transition on="submit" to="bindAndValidate" /> <transition on="checkTicketGrantingTicket" to="ticketGrantingTicketExistsCheck" /> </action-state> <!-- 远程回调页面,主要以JavaScript的方式回传一些参数用 --> <end-state id="remoteCallbackView" view="remoteCallbackView" /> <decision-state id="ticketGrantingTicketExistsCheck"> <if test="${flowScope.ticketGrantingTicketId != null}" then="hasServiceCheck" else="gatewayRequestCheck" /> </decision-state> <decision-state id="gatewayRequestCheck"> <if test="${externalContext.requestParameterMap['gateway'] != '' externalContext.requestParameterMap['gateway'] != null && flowScope.service != null}" then="redirect" else="remoteCallbackView" /> </decision-state><!--update--> <decision-state id="hasServiceCheck"> <if test="${flowScope.service != null}" then="generateServiceTicket" else="remoteCallbackView" /> </decision-state><!--update--> <!-- The "warn" action makes the determination of whether to redirect directly to the requested service or display the "confirmation" page to go back to the server. --> <decision-state id="warn"> <if test="${flowScope.warnCookieValue}" then="showWarningView" else="redirect" /> </decision-state> <action-state id="bindAndValidate"> <action bean="authenticationViaFormAction" /> <transition on="success" to="submit" /> <transition on="error" to="remoteCallbackView" /><!--update--> </action-state> <action-state id="submit"> <action bean="authenticationViaFormAction" method="submit" /> <transition on="warn" to="warn" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="remoteCallbackView" /><!--update--> </action-state> <action-state id="sendTicketGrantingTicket"> <action bean="sendTicketGrantingTicketAction" /> <transition on="success" to="serviceCheck" /> </action-state> <decision-state id="serviceCheck"> <if test="${flowScope.service != null}" then="generateServiceTicket" else="remoteCallbackView" /><!--update--> </decision-state> <action-state id="generateServiceTicket"> <action bean="generateServiceTicketAction" /> <transition on="success" to ="warn" /> <transition on="error" to="remoteCallbackView" /><!--update--> <transition on="gateway" to="redirect" /> </action-state> <!-- The "showWarningView" end state is the end state for when the user has requested privacy settings (to be "warned") to be turned on. It delegates to a view defines in default_views.properties that display the "Please click here to go to the service." message. --> <end-state id="showWarningView" view="casLoginConfirmView" /> <!-- The "redirect" end state allows CAS to properly end the workflow while still redirecting the user back to the service required. --> <end-state id="redirect" view="bean:dynamicRedirectViewSelector" /> <end-state id="viewServiceErrorView" view="viewServiceErrorView" /> <end-state id="viewServiceSsoErrorView" view="viewServiceSsoErrorView" /> <global-transitions> <transition to="viewServiceErrorView" on- exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException" / > <transition to="viewServiceSsoErrorView" on- exception="org.jasig.cas.services.UnauthorizedSsoServiceException" /> <transition to="viewServiceErrorView" on- exception="org.jasig.cas.services.UnauthorizedServiceException" /> </global-transitions> </flow>
以上文件根据原login-webflow.xml文件修改,粗体为修改部分。可以看到,我们在流程中增加了remoteLogin Action节点和remoteCallback View节点,下面我们配置remoteLogin节点:
在/WEB-INF/cas-servlet.xml文件中增加remoteLoginAction配置:
<bean id="remoteLoginAction" class="com.baidu.cas.web.flow.RemoteLoginAction" p:argumentExtractors-ref="argumentExtractors" p:warnCookieGenerator-ref="warnCookieGenerator" p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator" />
同时创建com.baidu.cas.web.flow.RemoteLoginAction类:
/** * 远程登陆票据提供Action. * 根据InitialFlowSetupAction修改. * 由于InitialFlowSetupAction为final类,因此只能将代码复制过来再进行修改. * * @author GuoLin */ public class RemoteLoginAction extends AbstractAction { /** CookieGenerator for the Warnings. */ @NotNull private CookieRetrievingCookieGenerator warnCookieGenerator; /** CookieGenerator for the TicketGrantingTickets. */ @NotNull private CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator; /** Extractors for finding the service. */ @NotEmpty private List<ArgumentExtractor> argumentExtractors; /** Boolean to note whether we've set the values on the generators or not. */ private boolean pathPopulated = false; protected Event doExecute(final RequestContext context) throws Exception { final HttpServletRequest request = WebUtils.getHttpServletRequest(context); if (!this.pathPopulated) { final String contextPath = context.getExternalContext().getContextPath(); final String cookiePath = StringUtils.hasText(contextPath) ? contextPath : "/"; logger.info("Setting path for cookies to: " + cookiePath); this.warnCookieGenerator.setCookiePath(cookiePath); this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath); this.pathPopulated = true; } context.getFlowScope().put("ticketGrantingTicketId", this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request)); context.getFlowScope().put("warnCookieValue", Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request))); final Service service = WebUtils.getService(this.argumentExtractors, context); if (service != null && logger.isDebugEnabled()) { logger.debug("Placing service in FlowScope: " + service.getId()); } context.getFlowScope().put("service", service); // 客户端必须传递loginUrl参数过来,否则无法确定登陆目标页面 if (StringUtils.hasText(request.getParameter("loginUrl"))) { context.getFlowScope().put("remoteLoginUrl", request.getParameter("loginUrl")); } else { request.setAttribute("remoteLoginMessage", "loginUrl parameter must be supported."); return error(); } // 若参数包含submit则进行提交,否则进行验证 if (StringUtils.hasText(request.getParameter("submit"))) { return result("submit"); } else { return result("checkTicketGrantingTicket"); } } public void setTicketGrantingTicketCookieGenerator( final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator) { this.ticketGrantingTicketCookieGenerator = ticketGrantingTicketCookieGenerator; } public void setWarnCookieGenerator(final CookieRetrievingCookieGenerator warnCookieGenerator) { this.warnCookieGenerator = warnCookieGenerator; } public void setArgumentExtractors( final List<ArgumentExtractor> argumentExtractors) { this.argumentExtractors = argumentExtractors; } }
以上粗体为修改部分,要求客户端必须传入loginUrl参数,且当客户端传入submit参数时,直接为其提交用户名密码
然后再配置remoteCallbackView显示节点,修改src/default_views.properties文件,增加remoteCallbackView配置:
### 配置远程回调页面
remoteCallbackView.(class)=org.springframework.web.servlet.view.JstlView
remoteCallbackView.url=/WEB-INF/view/jsp/default/ui/remoteCallbackView.jsp
创建/WEB-INF/view/jsp/default/ui/remoteCallbackView.jsp文件:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <html> <head> <script type="text/javascript"> var remoteUrl = "${remoteLoginUrl}?validated=true";<!--update 加参数validated=true--> // 构造错误消息 var errorMessage = ""; <spring:hasBindErrors name="credentials"> errorMessage = "&errorMessage=" + encodeURIComponent('<c:forEach var="error" items="${errors.allErrors}"><spring:message code="${error.code}" text="${error.defaultMessage}" /></c:forEach>'); </spring:hasBindErrors> // 构造service var serivce = ""; <c:if test="${service != null && service != ''}"> service = "&service=" + encodeURIComponent("${service}"); </c:if> // 跳转回去 window.location.href = remoteUrl + errorMessage + service; </script> </head> <body> ${remoteLoginMessage} </body> </html>
以上文件注意粗体部分validated=true,这里我们与客户端约定,当客户端登陆页面后带有参数validated=true时,不进行票据认证请求。这是因为,客户端登陆页面为http://clienthost/login.jsp,那么当用户访问URL http://clienthost/login.jsp时,客户端会重定向到CAS中央服务器请求TGT认证,但认证失败后CAS中央认证服务器会重定向到客户端登陆页面并显示登陆框,此时客户端必须以某种规则避免重新请求中央认证服务器认证, 在这里我们与客户端约定,当回发的请求为登陆页面且带有参数validated=true时即不转发TGT认证请求,即 http://
clienthost/login.jsp?validated=true 请求客户端不会重新发送TGT认证请求给中央认证服务器
到此,服务器端修改完成,下一篇介绍客户端如何构建
发表评论
-
让CAS退出后返回指定的页面
2011-09-27 09:37 2194CAS退出默认是转向CAS内置的退出页面,在实际应用中需要跳转 ... -
让CAS支持HTTP协议认证
2011-09-27 09:29 2271CAS默认使用HTTPS认证,在登录时使用HTTP方式也可以, ... -
CAS支持客户端自定义登陆页面——客户端篇
2011-09-25 00:49 1583让CAS支持客户端自定 ... -
让CAS支持客户端自定义登陆页面——原理篇
2011-09-25 00:10 1933最近忙死了,很久都 ... -
CAS3.0 定制验证(转)
2011-09-24 23:21 1576前言: CAS v2 定制自己的验证逻 ... -
cas单点登录介绍
2011-09-24 20:49 14801. 单点登录概述 所谓单点登录(SSO),只 ...
相关推荐
让CAS支持客户端自定义登陆页面——服务器篇[参考].pdf
让CAS支持客户端自定义登陆页面——服务器篇.docx
NULL 博文链接:https://yeminping.iteye.com/blog/411742
让CAS支持客户端自定义登陆页面----服务器篇--.doc
让CAS支持客户端自定义登陆页面----服务器篇.doc
让CAS支持客户端自定义登陆页面----服务器篇-.pdf
让CAS支持客户端自定义登陆页面----服务器篇--.doc
CAS客户端自定义核心过滤器,继承CAS的AbstractCasFilter自定义AuthenticationFilter
详细描述了cas 自定义登陆页面的配置与demo
cas客户端登录配置详细文档,支持客户端自定义登录和服务端统一登录。
包含cas源码、cas使用说明文档(包含配置信息)、连接数据库所需jar包、cas服务端自定义返回值等
这是boot2.0+shiro+pac4j+cas 整合项目 cas还可以自定义登陆页和认证校验数据库
cas4.2.7服务端+cas客户端+示例程序+环境搭建之客户端war包 一切跑不起来的程序和走不通的教程都是耍流氓,二话不说,先按照我的步骤把程序跑起来在说吧。 请看博客...
cas .net客户端的配置代码 CAS 与_net 集成的 “循环重定向”问题分析 - 邢少 - 博客园.mht根本不行的。 我自己另外找的一段代码
cas的客户端cas的客户端cas的客户端cas的客户端cas的客户端cas的客户端
CAS客户端获取用户保存至sessionUser
cas4.0版本的 单点登录 自定义页面。希望对你有用,最低资源分,辛苦分。有问题可以交流学习。谢谢
单点登录CAS.net客户端源码,已调试成功,需要在webconfig中将服务端地址以及跳转地址修改好即可
cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码cas客户端集成单点登录代码