之前的文章里介绍过通过GET的方式访问cas的登陆页,该页面实现自动提交,虽然可以实现登录功能,但是也有缺点,登录过程给人的感觉是通过GET实现,而不是通常的POST方式,而且GET的url需要传用户名密码,还是明文,用户体验及安全性都不好,因此,现在改进,通过ajax + jsonp的方式进行登录。
jsonp总的思路就是从跨域服务器端请求一段js,请求url里需要表明客户端callback函数名。返回的js内容是callback(服务器端数据内容),客户端接收js后会执行callback(接收的数据)。有三种实现方式,这里用的是jquery提供的$.getJSON
ajax + jsonp在这里的主要作用就是从cas处获取流水号:loginTicket以及flowExecutionKey
客户端表单如下,重点关注的参数是lt和execution。
<form action="http://passport/login?service=<%=res.getString("casService")%>" name="form1" method="post" id="loginForm" class="login">
<div class="log">
<input style="position:relative;top:-20px;left:-10px;" type="text" name="username"value="" placeholder="用户名" class="user" id="user_login">
<input style="position:relative;top:-20px;left:-10px;" type="password" name="password" value="" placeholder="密码" class="pwd" id="pwd_login">
<a style="position:relative;left:-10px;top:-20px;" href="javascript:void(0);" id="submit_login">
<span class="login_btn">登陆</span>
</a>
<span style="color:#FF0000;"><input type="hidden" name="lt" id="lt" value="" />
<input type="hidden" name="execution" id="execution" value="" /></span>
<input type="hidden" name="login_from" value="<%=res.getString("loginUrl")%>" />
<input type="hidden" name="_eventId" value="submit" />
</div>
</form>
以下为表单点击提交后绑定的js,首先通过jsonp从cas处获取lt与execution,然后做表单参数替换,最后提交表单。
$('#submit_login').bind("click",doLogin);
var doLogin = function(){
var serviceUrl='<%=res.getString("casService")%>';
$.getJSON("http://passport/login?action=getlt&service=" + serviceUrl + "&callback=?",
function(response) {
<span style="color:#FF0000;">document.getElementById("lt").value = response.lt;
document.getElementById("execution").value = response.execution;
$('#loginForm').submit();</span>
});
};
cas服务端的代码:
修改casLoginView.jsp
<%
String action = request.getParameter("action");
if (action != null && action.equals("getlt")) {
String callbackName = request.getParameter("callback");
String jsonData = "{\"lt\":\"" + request.getAttribute("loginTicket") + "\", \"execution\":\"" + request.getAttribute("flowExecutionKey") + "\"}";
String jsonp = callbackName + "(" + jsonData + ")";
response.setContentType("application/javascript");
response.getWriter().write(jsonp);
%>
登录测试,通过firebug抓包,可以看到cas返回的结果为:
jQuery19007072190695421778_1410847736691({"lt":"LT-6-xOrZYe5emXmLOthKgTWbeovEai9Trs", "execution":"e1s1"})
前面的callback函数名是jquery自动生成的。
经验证,满足跨域登录需求。