- 浏览: 359482 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
fengxiatao:
忘了说我邮箱了 757723745@qq.com
关于 CAS SSO 文章声明 -
fengxiatao:
请发一下最github地址给我好吗?不胜感激
关于 CAS SSO 文章声明 -
romyli:
求一个github地址.感谢分享
关于 CAS SSO 文章声明 -
zz210891470:
使用您的例子从服务器获取lt返回test-login 页面之后 ...
CAS 之自定义登录页实践 -
feiteyizu:
<div class="quote_title ...
CAS 之自定义登录页实践
1. 动机
用过 CAS 的人都知道 CAS-Server端是单独部署的,作为一个纯粹的认证中心。在用户每次登录时,都需要进入CAS-Server的登录页填写用户名和密码登录,但是如果存在多个子应用系统时,它们可能都有相应风格的登录页面,我们希望直接在子系统中登录成功,而不是每次都要跳转到CAS的登录页去登录。
2. 开始分析问题
其实仔细想一想,为什么不能直接在子系统中将参数提交至 cas/login 进行登录呢? 于是便找到了CAS在登录认证时主要参数说明:
service [OPTIONAL] 登录成功后重定向的URL地址;
username [REQUIRED] 登录用户名;
password [REQUIRED] 登录密码;
lt [REQUIRED] 登录令牌;
主要有四个参数,其中的三个参数倒好说,最关键的就是 lt , 据官方说明该参数是login ticket id, 主要是在登录前产生的一个唯一的“登录门票”,然后提交登录后会先取得"门票",确定其有效性后才进行用户名和密码的校验,否则直接重定向至 cas/login 页。
于是,便打开CAS-Server的登录页,发现其每次刷新都会产生一个 lt, 其实就是 Spring WebFlow 中的 flowExecutionKey值。 那么问题的关键就在于在子系统中如何获取 lt 也就是登录的ticket?
3. 可能的解决方案
一般对于获取登录ticket的解决方案可能大多数人都会提到两种方法:
- AJAX: 熟悉 Ajax 的可能都知道,它的请求方式是严格按照沙箱安全模型机制的,严格情况下会存在跨域安全问题。
- IFrames: 这也是早期的 ajax 实现方式,在页面中嵌入一个隐藏的IFrame,然后通过表单提交到该iframe来实现不刷新提交,不过使用这种方式同样会带来两个问题: a. 登录成功之后如何摆脱登录后的IFrame呢?如果成功登录可能会导致整个页面重定向,当然你能在form中使
用属性target="_parent",使之弹出,那么你如何在父页面显示错误信息呢?
b. 你可能会受到布局的限止(不允许或不支持iframe)
4. 通过JS重定向来获取login ticket (lt)
当第一次进入子系统的登录页时,通过 JS 进行redirect到cas/login?get-lt=true获取login ticket,然后在该login中的 flow 中检查是否包含get-lt=true的参数,如果是的话则跳转到lt生成页,生成后,并将lt作为该redirect url 中的参数连接,如 remote-login.html?lt=e1s1,然后子系统再通过JS解析当前URL并从参数中取得该lt的值放置登录表单中,即完成 lt 的获取工作。其中进行了两次 redirect 的操作。
5. 开始实践
首先,在我们的子系统中应该有一个登录页面,通过输入用户名和密码提交至cas认证中心。不过前提是先要获取到 login tickt id. 也就是说当用户第一次进入子系统的登录页面时,在该页面中会通过js跳转到 cas/login 中的获取login ticket. 在 cas/login 的 flow 中先会判断请求的参数中是否包含了 get-lt 的参数。
在cas的 login flow 中加入 ProvideLoginTicketAction 的流,主要用于判断该请求是否是来获取 lt,在cas-server端声明获取 login ticket action 类:
com.denger.sso.web.ProvideLoginTicketAction
/** * Opens up the CAS web flow to allow external retrieval of a login ticket. * * @author denger */ public class ProvideLoginTicketAction extends AbstractAction{ @Override protected Event doExecute(RequestContext context) throws Exception { final HttpServletRequest request = WebUtils.getHttpServletRequest(context); if (request.getParameter("get-lt") != null && request.getParameter("get-lt").equalsIgnoreCase("true")) { return result("loginTicketRequested"); } return result("continue"); } } // 如果参数中包含 get-lt 参数,则返回 loginTicketRequested 执行流,并跳转至 loginTicket 生成页,否则 则跳过该flow,并按照原始login的流程来执行。
并且将该 action 声明在 cas-servlet.xml 中:
<bean id="provideLoginTicketAction" class="com.denger.sso.web.ProvideLoginTicketAction" />
还需要定义 loginTicket 的生成页也就是当返回 loginTicketRequested 的 view:
viewRedirectToRequestor.jsp
<%@ page contentType="text/html; charset=UTF-8"%> <%@ page import="com.denger.sso.util.CasUtility"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <% String separator = ""; // 需要输入 login-at 参数,当生成lt后或登录失败后则重新跳转至 原登录页,并传入参数 lt 和 error_message String referer = request.getParameter("login-at"); referer = CasUtility.resetUrl(referer); if (referer != null && referer.length() > 0) { separator = (referer.indexOf("?") > -1) ? "&" : "?"; %> <html> <title>cas get login ticket</title> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script> var redirectURL = "<%=referer + separator%>lt=${flowExecutionKey}"; <spring:hasBindErrors name="credentials"> var errorMsg = '<c:forEach var="error" items="${errors.allErrors}"><spring:message code="${error.code}" text="${error.defaultMessage}" /></c:forEach>'; redirectURL += '&error_message=' + encodeURIComponent (errorMsg); </spring:hasBindErrors> window.location.href = redirectURL; </script> </head> <body></body> </html> <% } else { %> <script>window.location.href = "/member/login";</script> <% } %>
并且需要将该 jsp 声明在 default._views.properites 中:
### Redirect with login ticket view casRedirectToRequestorView.(class)=org.springframework.web.servlet.view.JstlView casRedirectToRequestorView.url=/WEB-INF/view/jsp/default/ui/viewRedirectToRequestor.jsp
相关 com.denger.sso.util.CasUtility 代码:
public class CasUtility { /** * Removes the previously attached GET parameters "lt" and "error_message" * to be able to send new ones. * * @param casUrl * @return */ public static String resetUrl(String casUrl) { String cleanedUrl; String[] paramsToBeRemoved = new String[] { "lt", "error_message", "get-lt" }; cleanedUrl = removeHttpGetParameters(casUrl, paramsToBeRemoved); return cleanedUrl; } /** * Removes selected HTTP GET parameters from a given URL * * @param casUrl * @param paramsToBeRemoved * @return */ public static String removeHttpGetParameters(String casUrl, String[] paramsToBeRemoved) { String cleanedUrl = casUrl; if (casUrl != null) { // check if there is any query string at all if (casUrl.indexOf("?") == -1) { return casUrl; } else { // determine the start and end position of the parameters to be // removed int startPosition, endPosition; boolean containsOneOfTheUnwantedParams = false; for (String paramToBeErased : paramsToBeRemoved) { startPosition = -1; endPosition = -1; if (cleanedUrl.indexOf("?" + paramToBeErased + "=") > -1) { startPosition = cleanedUrl.indexOf("?" + paramToBeErased + "=") + 1; } else if (cleanedUrl.indexOf("&" + paramToBeErased + "=") > -1) { startPosition = cleanedUrl.indexOf("&" + paramToBeErased + "=") + 1; } if (startPosition > -1) { int temp = cleanedUrl.indexOf("&", startPosition); endPosition = (temp > -1) ? temp + 1 : cleanedUrl .length(); // remove that parameter, leaving the rest untouched cleanedUrl = cleanedUrl.substring(0, startPosition) + cleanedUrl.substring(endPosition); containsOneOfTheUnwantedParams = true; } } // wenn nur noch das Fragezeichen vom query string übrig oder am // schluss ein "&", dann auch dieses entfernen if (cleanedUrl.endsWith("?") || cleanedUrl.endsWith("&")) { cleanedUrl = cleanedUrl.substring(0, cleanedUrl.length() - 1); } // parameter mehrfach angegeben wurde... if (!containsOneOfTheUnwantedParams) return casUrl; else cleanedUrl = removeHttpGetParameters(cleanedUrl, paramsToBeRemoved); } } return cleanedUrl; }
还有一处需要调整的地方就是当用户名和密码验证失败后,应该重新返回至子系统登录页,也就是 login-at 参数值,此时同样需要重新生成 login ticket。 于是找到 cas 登录验证处理 action :org.jasig.cas.web.flow.AuthenticationViaFormAction 修改 submit方法 中代码下如:
try { WebUtils.putTicketGrantingTicketInRequestScope(context, this.centralAuthenticationService.createTicketGrantingTicket(credentials)); putWarnCookieIfRequestParameterPresent(context); return "success"; } catch (final TicketException e) { populateErrorsInstance(e, messageContext); // 当验证失败后,判断参数中是否获否 login-at 参数,如果包含的话则跳转至 login ticket 获取页 String referer = context.getRequestParameters().get("login-at"); if (!org.apache.commons.lang.StringUtils.isBlank(referer)) { return "errorForRemoteRequestor"; } return "error"; }
接下来要做的就是将该action 的处理加入到 login-webflow.xml 请求流中:
<on-start> <evaluate expression="initialFlowSetupAction" /> </on-start> <!-- 添加如下配置 :--> <action-state id="provideLoginTicket"> <evaluate expression="provideLoginTicketAction"/> <transition on="loginTicketRequested" to ="viewRedirectToRequestor" /> <transition on="continue" to="ticketGrantingTicketExistsCheck" /> </action-state> <view-state id="viewRedirectToRequestor" view="casRedirectToRequestorView" model="credentials"> <var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" /> <binder> <binding property="username" /> <binding property="password" /> </binder> <on-entry> <set name="viewScope.commandName" value="'credentials'" /> </on-entry> <transition on="submit" bind="true" validate="true" to="realSubmit"> <set name="flowScope.credentials" value="credentials" /> <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" /> </transition> </view-state> <!---添加结束处 ---> <decision-state id="ticketGrantingTicketExistsCheck"> <if test="flowScope.ticketGrantingTicketId neq null" then="hasServiceCheck" else="gatewayRequestCheck" /> </decision-state> <!-- ..... 省略中间代码 ...--> <action-state id="realSubmit"> <evaluate expression="authenticationViaFormAction.submit(flowRequestContext, flowScope.credentials, messageContext)" /> <transition on="warn" to="warn" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> <!--加入该transition , 当验证失败之后重新获取login ticket --> <transition on="errorForRemoteRequestor" to="viewRedirectToRequestor" /> </action-state>
好了,至此,对server端的调整基本上已经大功告成了,现在开始写一个测试远程登录的 html:
<!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>Test remote Login using JS</title> <script type="text/javascript"> function prepareLoginForm() { $('myLoginForm').action = casLoginURL; $("lt").value = loginTicket; } function checkForLoginTicket() { var loginTicketProvided = false; var query = ''; casLoginURL = 'http://192.168.6.1:8080/member/login'; thisPageURL = 'http://192.168.6.1:8080/member/test-login.html'; casLoginURL += '?login-at=' + encodeURIComponent (thisPageURL); query = window.location.search; query = query.substr (1); var param = new Array(); //var value = new Array(); var temp = new Array(); param = query.split ('&'); i = 0; // 开始获取当前 url 的参数,获到 lt 和 error_message。 while (param[i]) { temp = param[i].split ('='); if (temp[0] == 'lt') { loginTicket = temp[1]; loginTicketProvided = true; } if (temp[0] == 'error_message') { error = temp[1]; } i++; } // 判断是否已经获取到 lt 参数,如果未获取到则跳转至 cas/login 页,并且带上请求参数 get-lt=true。 第一次进该页面时会进行一次跳转 if (!loginTicketProvided) { location.href = casLoginURL + '&get-lt=true'; } } var $ = function(id){ return document.getElementById(id); } checkForLoginTicket(); onload = prepareLoginForm; </script> </head> <body> <h2>Test remote Login using JS</h2> <form id="myLoginForm" action="" method="post"> <input type="hidden" name="_eventId" value="submit" /> <table> <tr> <td id="txt_error" colspan="2"> <script type="text/javascript" language="javascript"> <!-- if ( error ) { error = decodeURIComponent (error); document.write (error); } //--> </script> </td> </tr> <tr> <td>Username:</td> <td><input type="text" value="" name="username" ></td> </tr> <tr> <td>Password:</td> <td><input type="text" value="" name="password" ></td> </tr> <tr> <td>Login Ticket:</td> <td><input type="text" name="lt" id="lt" value=""></td> </tr> <tr> <td>Service:</td> <td><input type="text" name="service" value="http://www.google.com.hk"></td> </tr> <tr> <td align="right" colspan="2"><input type="submit" /></td> </tr> </table> </form> </body> </html>
开始测试,直接访问:http://192.168.6.1:8080/member/test-login.html 发现进行了二次重定向,进入该页面 js 未发现 lt 参数,于是重定向到 http://192.168.6.1:8080/member/login?login-at=http://192.168.6.1:8080/member/test-login.html &get-lt=true ,然后又从该页重定向到 http://192.168.6.1:8080/member/test-login.html?lt=e1s1 ,可以发现,其中的 lt 就是我们所需要的 login ticket参数。
6. 不足之处
1. 可以发现,每次用户访问 登录页面时都要进行两次重定向的操作,虽然很快,但是在有些情况仍然能看到登录页面闪了一下。 当然这也是有办法可以解决的!
2. 可以发现,当登录失败之后,会将错误信息以参数的方式进行传递,看上去这并非专业做法。可以定义一些错误标识,比如 1 是用户名或密码错误之类的。
PS:参考:https://wiki.jasig.org/display/CAS/Using+CAS+without+the+Login+Screen 如有不足之处,欢迎指正~
评论
65 楼
zz210891470
2017-02-21
使用您的例子从服务器获取lt返回test-login 页面之后又回去取lt了,陷入了死循环页面停不下来,,,能上份完整的源码吗。。。如果可以的话 您能发一份到我邮箱吗 517418860@qq.com
64 楼
feiteyizu
2016-08-03
WANTAWAY314 写道
这种方法适合移动端的单点登录不?大神
移动端的单点登录 有单独的 cas restful api
63 楼
WANTAWAY314
2016-03-21
这种方法适合移动端的单点登录不?大神
62 楼
feiteyizu
2015-10-10
按照文章是可以配成功的,高版本cas按章原方式会直接跳回cas登陆页问题,
高版本的cas的lt是${loginTicket},可以在基础上调整下,provideLoginTicket流程里跳到生成loginTicket的流程里生成loginTicket后在跳回viewRedirectToRequestor,以下为修改处:
<action-state id="provideLoginTicket">
<evaluate expression="provideLoginTicketAction"/>
<!-- 生成loginTicket-->
<transition on="loginTicketRequested" to ="generateLoginTicket" />
<transition on="continue" to="ticketGrantingTicketExistsCheck" />
</action-state>
<action-state id="generateLoginTicket">
<evaluate expression="generateLoginTicketAction.generate(flowRequestContext)" />
<!--
<transition on="generated" to="viewLoginForm" />
生成loginTicket后跳回viewRedirectToRequestor
-->
<transition on="generated" to="viewRedirectToRequestor" />
</action-state>
viewRedirectToRequestor.jsp中获取${loginTicket}传回登陆页就可以了,供研究的朋友参考
高版本的cas的lt是${loginTicket},可以在基础上调整下,provideLoginTicket流程里跳到生成loginTicket的流程里生成loginTicket后在跳回viewRedirectToRequestor,以下为修改处:
<action-state id="provideLoginTicket">
<evaluate expression="provideLoginTicketAction"/>
<!-- 生成loginTicket-->
<transition on="loginTicketRequested" to ="generateLoginTicket" />
<transition on="continue" to="ticketGrantingTicketExistsCheck" />
</action-state>
<action-state id="generateLoginTicket">
<evaluate expression="generateLoginTicketAction.generate(flowRequestContext)" />
<!--
<transition on="generated" to="viewLoginForm" />
生成loginTicket后跳回viewRedirectToRequestor
-->
<transition on="generated" to="viewRedirectToRequestor" />
</action-state>
viewRedirectToRequestor.jsp中获取${loginTicket}传回登陆页就可以了,供研究的朋友参考
61 楼
zhoup_1234
2015-04-23
您是按什么版本 开发的呢? 我现在可以取到值 lt 可是post 过去就跳登录页。是什么情况呢
60 楼
denger
2015-03-21
59 楼
黑黑yy
2015-03-17
黑黑yy 写道
casLoginURL = 'http://192.168.6.1:8080/member/login';
thisPageURL = 'http://192.168.6.1:8080/member/test-login.html';
测试页面里面配的都是服务端,请问下客户端怎么做呢,整个文章都没提到过客户端
thisPageURL = 'http://192.168.6.1:8080/member/test-login.html';
测试页面里面配的都是服务端,请问下客户端怎么做呢,整个文章都没提到过客户端
楼主帮忙指导下,谢谢
58 楼
denger
2015-03-17
inlhx 写道
这个太复杂了并且不容易成功,试试这个方式:http://inlhx.iteye.com/blog/2175859 直接cas ajax提交,连源码都不用改
这个方法比较暴力~ 不推荐, 其中还需要 ajax 下载和解析 login 页的 html,对于稍大型 应用 来说非常不适合 。。。 如果 html 代码结构发生变更了,就歇了
57 楼
inlhx
2015-03-17
这个太复杂了并且不容易成功,试试这个方式:http://inlhx.iteye.com/blog/2175859 直接cas ajax提交,连源码都不用改
56 楼
黑黑yy
2015-03-17
casLoginURL = 'http://192.168.6.1:8080/member/login';
thisPageURL = 'http://192.168.6.1:8080/member/test-login.html';
测试页面里面配的都是服务端,请问下客户端怎么做呢,整个文章都没提到过客户端
thisPageURL = 'http://192.168.6.1:8080/member/test-login.html';
测试页面里面配的都是服务端,请问下客户端怎么做呢,整个文章都没提到过客户端
55 楼
denger
2015-03-03
目前按以上方式上线的产品:
http://uc.noahedu.com/ (CAS client)
http://passport.noahedu.com (CAS Server)
不明白的看看请求及交互吧~~别乱说误导人~
http://uc.noahedu.com/ (CAS client)
http://passport.noahedu.com (CAS Server)
不明白的看看请求及交互吧~~别乱说误导人~
54 楼
denger
2015-03-03
honglei0412 写道
honglei0412 写道
楼主您做的这个案例的登录页面是在cas的服务端做了一个登录页面 ,而不是在子系统中做的登录页面 ?是不?
这样做有什么意思啊 楼主?
引用
,都需要进入CAS-Server的登录页填写用户名和密码登录,但是如果存在多个子应用系统时,它们可能都有相应风格的登录页面,我们希望直接在子系统中登录成功,而不是每次都要跳转到CAS的登录页去登录。
看不明白吗? 每个子系统自定义登录页,一开始就说了。
53 楼
honglei0412
2015-03-03
honglei0412 写道
楼主您做的这个案例的登录页面是在cas的服务端做了一个登录页面 ,而不是在子系统中做的登录页面 ?是不?
这样做有什么意思啊 楼主?
52 楼
honglei0412
2015-03-03
楼主您做的这个案例的登录页面是在cas的服务端做了一个登录页面 ,而不是在子系统中做的登录页面 ?是不?
51 楼
honglei0412
2015-02-27
这个viewRedirectToRequestor.jsp 页面中的 else <script>window.location.href = "/member/login";</script> 直接就调回到登录页面了 ,下来就死循环了 ,楼主不知道发现了没有?
50 楼
honglei0412
2015-02-27
楼主您的那个案例有跑过吗? 有没有出现过登陆后直接死循环的现象?
49 楼
ruodian
2014-11-06
楼主 请问login.jsp的页面是怎么样的?我执行到
http://192.168.6.1:8080/member/login?login-at=http://192.168.6.1:8080/member/test-login.html &get-lt=true 的时候
后台执行到
if (request.getParameter("get-lt") != null && request.getParameter("get-lt").equalsIgnoreCase("true")) {
return result("loginTicketRequested");
}
return result("continue");
取到的url是 /cas/login?service=http%3A%2F%2Flocalhost%3A8081%2Fpsbc%2Fj_spring_cas_security_check
就没get-lt了
http://192.168.6.1:8080/member/login?login-at=http://192.168.6.1:8080/member/test-login.html &get-lt=true 的时候
后台执行到
if (request.getParameter("get-lt") != null && request.getParameter("get-lt").equalsIgnoreCase("true")) {
return result("loginTicketRequested");
}
return result("continue");
取到的url是 /cas/login?service=http%3A%2F%2Flocalhost%3A8081%2Fpsbc%2Fj_spring_cas_security_check
就没get-lt了
48 楼
cjdxhjj
2014-05-04
你好,博主,我使用的3.5.2.1,登陆需要execution 参数和lt参数,execution像你们例子的,4位如e4s1,不过lt是形如LT-3-eIDsiRQJg53tb40OEUwrii2b5TIvOP这样的,请问我怎么取到
47 楼
saivicky1314
2014-03-28
{"failure":"true","exception.message":"org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'viewRedirectToRequestor' of flow 'login'","exception.stacktrace":"org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'viewRedirectToRequestor' of flow 'login'\r\n\tat总是报这个错
46 楼
saivicky1314
2014-03-28
cas单点登录可以发一份到我的吗2848182634@qq.com
发表评论
-
关于 CAS SSO 文章声明
2015-03-21 14:39 3127由于几年前写了几篇 CAS 系列的文章,之后陆续有人参照文章去 ... -
CAS 之 跨域 Ajax 登录实践
2011-07-08 01:36 27558因最近经常有时候被一些朋友问到关于 CAS 跨全域下的 Aja ... -
新浪微博如何实现 SSO 的分析
2011-05-10 14:44 24769最近在使用sina微博时,经常性交替使用 weibo ... -
淘宝如何跨域获取Cookie分析
2011-04-13 10:39 20467Move to: http://www.iteye.com/t ... -
CAS 之 集成RESTful API
2011-03-23 20:59 44256最近因为公司另一款基于C/S的产品也需要整合到CAS ... -
CAS 之 实现用户注册后自动登录
2010-11-08 16:22 186101. 关于CAS的介绍不再累述,我想涉及过SSO同学 ...
相关推荐
【标题】"CAS修改登录页"是一个针对中央认证服务(Central Authentication Service,简称CAS)的定制化实践。在单点登录(Single Sign-On,SSO)系统中,CAS扮演着核心角色,它提供了统一的身份验证服务,使得用户只...
CAS(Central Authentication Service)是Java开发的一个开源的单点登录...通过学习和实践,你可以掌握CAS的核心概念,实现自定义认证策略,以及优化客户端集成,从而为你的项目构建一个强大而安全的单点登录系统。
标题中的“让CAS支持客户端自定义登陆页面——客户端篇”表明了本文主要探讨的是如何在中央认证服务(Central Authentication Service, CAS)系统中,允许客户端应用程序实现自定义登录页面的配置与实现。CAS是一个...
9. **API扩展**:如果需要在登录页面添加自定义功能,如集成第三方服务,可以通过实现 CAS 提供的 REST API 或者 WebService API 来实现。 10. **文档更新**:任何代码更改后,确保更新相关的开发者文档,以便团队...
总结,实现CAS系统下不同应用展示不同登录页的关键在于理解CAS的工作机制,并对服务器端进行适当的配置和扩展。通过修改登录视图、动态选择页面和定义应用标识,我们可以为用户提供更加个性化和友好的登录体验。在...
由于实际内容没有给出,我将基于常见的CAS自定义登录流程进行讲解。 首先,理解CAS的工作原理至关重要。当用户尝试访问一个受CAS保护的应用时,会被重定向到CAS服务器的登录页面。在这里,用户输入凭证,如用户名和...
这通常涉及向CAS服务器发送请求,获取认证URL(即CAS登录页),并在用户登录成功后,处理CAS返回的服务票证。 4. iframe技术:使用HTML的iframe元素,将CAS的登录页面嵌入到你的应用中,使得用户可以在不离开当前...
本文主要介绍如何让CAS(Central Authentication Service)支持客户端自定义登录页面,主要集中在服务器端的修改。CAS是一种开源的身份验证框架,它提供单点登录(SSO)功能,通常用于集中管理多个应用系统的用户...
本文将详细介绍如何在CAS服务器端进行配置,以便支持客户端自定义登录页面。 首先,我们要明确修改的目标是不影响CAS原有的统一登录界面功能,同时尽可能简化客户端的实现,并确保原有功能的安全性。但要注意的是,...
在本文中,我们将深入探讨CAS单点登录的基本原理、工作流程以及如何通过提供的Demo进行实践操作。 **CAS基本原理** CAS的核心思想是用户只需在一个应用系统中验证身份,之后访问其他所有支持CAS的应用系统时都不再...
可以使用CAS提供的工具或者开发自定义的测试脚本来模拟用户登录和应用间的跳转。 在提供的PDF文件`cas单点登录(一).pdf`和`cas单点登录(二).pdf`中,应该详细涵盖了这些步骤,以及更深入的技术细节,包括可能...
**CAS单点登录配置大全** CAS(Central Authentication Service,中央认证服务)是一种广泛使用的开源单点登录(Single Sign-On,SSO)协议。它允许用户通过一个统一的认证系统访问多个应用系统,而无需在每个系统...
**基于Cas的单点登录实现** 单点登录(Single Sign-On,简称SSO)是一种在多个应用系统中,...通过学习和实践这个示例应用,开发者可以深入理解Cas和Shiro的结合使用,以及SSO在实际项目中的应用,提升系统安全性。
CAS(Central Authentication Service)是...总之,"cas单点登录4.0"的资源对于学习和实践CAS单点登录系统非常重要。无论是部署和配置CAS服务器,还是深入研究其源代码,都能帮助我们更全面地理解和掌握单点登录技术。
总结,通过学习和实践这个"利用CAS实现单点登录的完整实例",你将掌握如何使用Jasig CAS构建一个高效的单点登录系统,从而提升用户体验,简化身份验证管理,并加强系统的安全性。记得深入理解每个步骤,并根据实际...
在这个" CAS单点登录示例 "中,你可以通过实践来理解这些概念,探索如何设置CAS服务器,配置客户端,以及如何进行用户认证。通过这个示例,你将更深入地了解SSO的工作原理,为实际项目中的身份验证解决方案打下坚实...
6. **定制化**:根据应用需求,可能需要自定义CAS客户端的行为,如自定义登录页面、错误处理或者用户信息的解析。 7. **安全考虑**:集成CAS后,应确保网络通信的安全,通常采用HTTPS协议来加密传输数据。同时,对...
通过"SSO之CAS单点登录实例演示",我们可以实践这些步骤,了解如何设置和运行一个基本的CAS环境,进一步理解SSO的工作原理和实际应用。这个实例将帮助我们更好地掌握如何为自己的应用实现SSO功能,提升系统的安全性...
[置顶] SSO单点登录系列3:cas-server端配置认证方式实践(数据源+自定义java类认证) http://blog.csdn.net/ae6623/article/details/8851801 [置顶] SSO单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas...