CAS客户端使用Ajax登陆(即保留原有客户端登录页面)
2017-11-13 19:14
645 查看
前言
因为对项目的不熟悉,在使用CAS的时候,踩了蛮多的坑,前面的文章提到了怎么跟shiro集成,可以说是花了比较多的时间。而实际的需求却不止于此。公司希望保留原有应用的登录页面。这个可又是一个大坑啊。自己花了几天时间来实现这个需求。逛了不知道多少的帖子。综合网上的帖子来看,在保留原有的登陆页面上有两个实现的思路,一个是通过Ajax+JSONP在前端做,另一个是在后端用HttpClient来实现。总体的思路都是模拟请求登陆页,先获取lt及execution再获取Ticket。
首先用的HttpClient来实现,但是后面发现登陆的问题是解决了,但是存在Cookie跨域的问题,这样子就失去了单点登录的意义了。(虽然错了后面会贴出来Demo)
由于没有找到解决方案,后面采取Ajax+JSONP来实现,这种方式比较简单。虽然保留了客户端应用的界面,但是原有的登陆方法是已经弃用了的。只是保留了界面,原来的CASclient的配置还是要配置。shiro+cas的集成前篇已经说了,所以这里就不再重复贴了。需要的可以找一下前面的帖子。[直达链接]
一、使用Ajax+JSONP实现
1、在server的casLoginView.jsp页面添加如下代码,用来获取lt及execution
<% 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); }else{ %> <!--.....原来页面的HTML代码......--> <% } %>
2、修改客户端
[b]2.1、修改客户端登录页面表单[/b]添加lt、execution及_eventId表单字段。
修改表单提交的action为携带service参数的server地址
<form method="post" action="http://www.cas.com/login?service=http://127.0.0.1:8080/cas_client/a/cas" id="loginForm"> <input type="text" id="username" name="username" value="${username}" title="请输入用户名" placeholder="用户名" class="login1form_control login1uname"/> <input type="password" id="password" name="password" title="请输入密码" placeholder="密码" class="login1form_control login1pword login1m-b"/> <%--CAS单点登录--%> <input type="hidden" name="lt" id="lt" value=""/> <input type="hidden" name="execution" id="execution" value=""/></span> <input type="hidden" name="_eventId" value="submit"/> <%--CAS单点登录--%> <button id="login1btn" class="login1btn login1btn-success login1btn-block" type="submit">登录 </button> </form>
[b]2.2、利用JSONP获取lt及execution参数[/b]
添加如下js,用来初始化lt、execution的值
注意修改server地址及service参数
<script type="text/javascript"> $(function(){ $.getJSON("http://www.cas.com/login?action=getlt&service=http://127.0.0.1:8080/cas_client/a/cas&callback=?", function (data) { $("#lt").val(data.lt); $("#execution").val(data.execution); }) }) </script>
这种方式只需在配置好CAS之后修改页面即可。
二、使用HttpClient来实现
Demo如下,这种方式仅供参考,未解决跨域问题import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URI; import java.util.HashMap; import java.util.List; import java.util.Map; /** * A example that demonstrates how HttpClient APIs can be used to perform * form-based logon. 一个例子,演示了如何HttpClient API可用于执行基于表单的登录。 */ public class ClientFormLogin { private static final String USERNAME = "admin"; private static final String PASSWORD = "123456"; private static final String CAS_LOGIN_URL = "http://www.cas.com/login?service=http://127.0.0.1:8081/cas_client/a/cas"; public static void main(String[] args) throws Exception { BasicCookieStore cookieStore = new BasicCookieStore(); CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build(); try { //访问Server登陆页面获得Cookie HttpGet initServerGet = new HttpGet(CAS_LOGIN_URL); CloseableHttpResponse response1 = httpclient.execute(initServerGet); try { HttpEntity entity = response1.getEntity(); System.out.println("Login form get: " + response1.getStatusLine()); EntityUtils.consume(entity); System.out.println("Initial set of cookies:"); List<Cookie> cookies = cookieStore.getCookies(); if (cookies.isEmpty()) { System.out.println("None"); } else { for (int i = 0; i < cookies.size(); i++) { System.out.println("- " + cookies.get(i).toString()); } } } finally { response1.close(); } //获取lt及execution参数 Map<String, String> map = doCasLoginRequest(httpclient, CAS_LOGIN_URL); //封装参数 HttpUriRequest login = RequestBuilder.post() .setUri(new URI(CAS_LOGIN_URL)) .addParameter("username", USERNAME) .addParameter("password", PASSWORD) .addParameter("lt", map.get("lt")) .addParameter("_eventId", "submit") .addParameter("submit", "登录") .addParameter("execution", map.get("execution")).build(); CloseableHttpResponse response2 = httpclient.execute(login); String location = response2.getFirstHeader("Location").getValue(); System.out.println(location.substring(location.indexOf("?ticket=") + 8)); Header[] tgtHead = response2.getHeaders("Set-Cookie"); //无需重新再请求,否则会导致重定向过多 HttpGet httpGet = new HttpGet(location); httpGet.setHeaders(tgtHead); CloseableHttpResponse response3 = httpclient.execute(httpGet); System.out.println("请求访问地址状态码: " + response3.getStatusLine()); String body = EntityUtils.toString(response3.getEntity()); try { HttpEntity entity = response2.getEntity(); System.out.println("Login form get: " + response2.getStatusLine()); EntityUtils.consume(entity); System.out.println("Post logon cookies:"); List<Cookie> cookies = cookieStore.getCookies(); if (cookies.isEmpty()) { System.out.println("None"); } else { for (int i = 0; i < cookies.size(); i++) { System.out.println("- " + cookies.get(i).toString()); } } } finally { response2.close(); } } finally { httpclient.close(); } } private static Map<String, String> doCasLoginRequest(HttpClient httpclient, String url) throws IOException { Map<String, String> result = new HashMap<>(16); HttpGet httpget = new HttpGet(url); HttpResponse response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); BufferedReader rd = new BufferedReader(new InputStreamReader( entity.getContent(), "UTF-8")); String tempLine = rd.readLine(); String lt = "<input type=\"hidden\" name=\"lt\" value=\""; String execution = "<input type=\"hidden\" name=\"execution\" value=\""; while (tempLine != null) { int lt_index = tempLine.indexOf(lt); if (lt_index != -1) { String s1 = tempLine.substring(lt_index + lt.length()); int index1 = s1.indexOf("\""); if (index1 != -1) { result.put("lt", s1.substring(0, index1)); } } int execution_index = tempLine.indexOf(execution); if (execution_index != -1) { String s1 = tempLine.substring(execution_index + execution.length()); int index1 = s1.indexOf("\""); if (index1 != -1) { result.put("execution", s1.substring(0, index1)); } } tempLine = rd.readLine(); } if (entity != null) { entity.consumeContent(); } return result; } }
参考文章:http://blog.csdn.net/just_lion/article/details/39316169
http://blog.csdn.net/mengtianyalll/article/details/50073099
相关文章推荐
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(9):服务器端和客户端数据类型的自动转换:DataTable和DataSet
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(6):服务器端和客户端数据类型的自动转换:复杂类型
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法:服务器端和客户端数据类型的自动转换:复杂类型
- 让CAS支持客户端自定义登陆页面——服务器篇
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(6):服务器端和客户端数据类型的自动转换:复杂类型
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(9):服务器端和客户端数据类型的自动转换:DataTable和DataSet
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(9):服务器端和客户端数据类型的自动转换:DataTable和DataSet
- 使用ajax的登录页面
- 登录框一直在页面中间且使用Ajax无刷新登录
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(7):服务器端和客户端数据类型的自动转换:泛型集合类型
- Using CAS without the Login Screen(不使用cas登陆页面)
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(4):异步通讯层生成的客户端代理类、使用HTTP GET进行调用
- CAS之客户端使用——基于CAS的单点登陆的研究(下)
- [置顶] CAS之客户端使用——基于CAS的单点登陆的研究(下)
- 让CAS支持客户端自定义登陆页面——原理篇
- 让CAS支持客户端自定义登陆页面
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(10):服务器端和客户端数据类型的自动转换:以XML方式序列化数据、小结
- 在登录页面中js进行正则验证电话号码和邮箱地址,并使用ajax进行用户ID的数据库验证
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(10):服务器端和客户端数据类型的自动转换:以XML方式序列化数据、小结
- 让CAS支持客户端自定义登陆页面——客户端篇