天天看点

自定义客户端登录CAS服务器-iframe实现

环境:

tomcat7.05

cas-server-3.4.5

cas-client-3.2.0

呃,你没看错,是用iframe实现。这个不算是一个好的方案,甚至我自己都有点看不起自己的感觉。但却是一个简单易用并最能兼容以后CAS-server更新的一套方案(还用说么,你都用iframe了)。目前项目比较紧急没时间去研究Spring WebFlow 3的情况下只好出此下策了,大神请喷。 :oops:

这个题目相信使用过CAS的朋友都不会陌生了。由于安全性的问题,CAS-Server 一直不建议把验证放到客户端之上。所以不提供验证表单的接口,或者说必须我们去开发扩展。而在实际应用中,很多单点登录的表单却是在客户端中完成,例如在某门户首页的登陆框。这些是不可能在Cas-Server上直接改造成门户的。所以造成了必须在门户中进行CAS服务器表单验证的局面。

当然这一切都是建立在我目前对CAS的熟悉程度来说的,欢迎指教。

其实网上也有比较多的方案,但基本上是版本对不上了,我也逼于无奈才采取这种比较傻瓜式的方法进行验证。

不管怎样,虽然觉得说名字大家都知道实现原理了,但也应该照顾一些不理解的。

1.自己的登录页面中用iframe加载cas-server的登录页面。

2.当用户输入账号密码登录的时候,同时把账号密码信息传入cas-server登录页面,并且提交。

3.若成功则刷新页面,登录窗口消失。若失败则提示用户。这个iframe相对用户来说是不可见的。

引用一下前辈的客户端实现目标描述:

[quote]客户端实现目标

客户端实现主要需要满足5个case:

1. 用户未在中央认证服务器登陆,访问客户端受保护资源时,客户端重定向到中央认证服务器请求TGT认证,认证失败,转回客户端登陆页面,保证受保护资源URL信息不丢失

2. 用户未在中央认证服务器登陆,访问客户端登陆页面时,客户端重定向到中央认证服务器请求TGT认证,认证失败,转回客户端登陆页面,此次登录页面不再受保护,允许访问

3. 用户已在中央认证服务器登陆,访问客户端受保护资源时,客户端重定向到中央认证服务器请求TGT认证,认证成功,直接转回受保护资源

4. 用户在客户端登陆页面提交用户名密码,客户端将用户名密码信息提交给服务器端,认证失败,转回客户端登陆页面,携带失败信息并保证转到登陆页面前受保护资源URL信息不丢失

5. 用户在客户端登陆页面提交用户名密码,客户端将用户名密码信息提交给服务器端,认证成功,转回转到登陆页面前受保护资源[/quote]

而技术方面没什么太大的要求,最主要是一些基本的javascript知识。

[b][size=medium]一、改造Cas-Server默登陆页面,让它对反馈信息支持。[/size][/b]

打开 WEB-INF\view\jsp\default\ui\casLoginView.jsp

在<jsp:directive.include file="includes/bottom.jsp" />之上加上以下代码

<%-- add by Kenny Begin --%>
<script type="text/javascript">
    function showErrorMsg(){
        if(window.parent.window.document.getElementById('cas_serverFrame')){
            var statusEl = document.getElementById('status');
            if(statusEl && statusEl.className === 'errors'){
                window.parent.window.alert('账号或密码有误!');
            }
        }
    }
    if(top.location !== self.location){
        showErrorMsg();
    }
</script>
<%-- add by Kenny End --%>
           

其中cas_serverFrame为我自定义登陆页面中iframe的id,稍后会看到。判断其实可以简化些,或者其他可以自由发挥了,供参考。

查找页面中的submit表单提交按钮,如果name为submit的话记得改掉(默认是name=submit),[b][color=red]因为如果在html中有任何一个元素的name属性为submit时,则用javascript操作form元素时是无法执行submit(),会提示'不存在的方法'[/color][/b]。这个卡了我不少时间。

[b][size=medium]二、门户中自定义登陆表单页面[/size][/b]

<%-- 
    Document   : login
    Created on : 2011-1-11, 3:07:16
    Author     : Kenny
--%>

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>远程CAS客户端登陆页面</title>
    <link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/styles/main.css" target="_blank" rel="external nofollow"  />
    <script type="text/javascript" src="js/clientLogin.js"> </script>
</head>
<body>
    <h1>远程CAS客户端登陆页面</h1>
    <% if (request.getRemoteUser() == null) { %>
        <div id="errorMessage"></div>
        <form id="myLoginForm" action="https://localhost:8443/cas-server/login" method="post">
            <input type="hidden" id="service" name="service" value="">
            <input type="hidden" name="loginUrl" value="https://localhost:8443/sso_demo/login.jsp">
            <input type="hidden" name="submit" value="true" />
            <table>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" id="username" name="username"></td>
                </tr>
                <tr>
                    <td>密  码:</td>
                    <td><input type="password" id="password" name="password"></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="button" value="登陆" id="loginButt" /></td>
                </tr>
            </table>
        </form>
        <iframe style="display:none;" src="" name="cas_serverFrame"  id="cas_serverFrame" ></iframe>
        <script type="text/javascript">
            loadedIFrame(window.event);
        </script>
    <% } else { %>
        <div class="welcome">您好:<%= request.getRemoteUser() %></div>
        <div id="logout">
            <a href="https://localhost:8443/cas-server/logout?service=https://localhost:8443/sso_demo/login.jsp" target="_blank" rel="external nofollow" >单点登出</a>
        </div>
    <% } %>
</body>
</html>
           

[b][size=medium]三、登陆页面中用到的clientLogin.js[/size][/b]

[b][size=medium]四、为了实现验证成功后跳转到验证之前的URL资源,cas-server的验证成功后的redirect修改是必不可少了。[/size][/b]

①修改WEB-INF/login-webflow.xml文件

搜索<end-state id="viewGenericLoginSuccess" view="casLoginGenericSuccessView" />

修改为

<end-state id="viewGenericLoginSuccess" view="redirectView" />
           

②添加redirectView

打开WEB-INF\classes\default_views.properties

增加如下字段:

### 跳转回调页面
redirectView.(class)=org.springframework.web.servlet.view.JstlView
redirectView.url=/WEB-INF/view/jsp/default/ui/redirect.jsp
           

③新建/WEB-INF/view/jsp/default/ui/redirect.jsp

代码参考如下:

附上本帖子提及过的文件和我测试的客户端项目,详细见附件。

题外:

本次开发是在netbeans上开发的,所以用eclipse的朋友导入demo项目可能要麻烦一些。不知道为何我的MyEclipse上的m4eclipse怎么没了,所以用不了maven插件,懒得弄就直接用netbeans了,因为NetBeans 6.9版本对maven支持很好。

参考:

[url]http://fallenlord.blogbus.com/logs/36905130.html[/url]

[url]http://fallenlord.blogbus.com/logs/36907990.html[/url]

[url]http://fallenlord.blogbus.com/logs/36907044.html[/url]

继续阅读