CAS客户端使用Ajax登陆(即保留原有客户端登录页面)

前言

    因为对项目的不熟悉,在使用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、修改客户端
  2.1、修改客户端登录页面表单

    添加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>
  2.2、利用JSONP获取lt及execution参数

    添加如下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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CAS(Central Authentication Service)是一种单点登录协议,用于实现在多个应用系统中进行统一的身份认证和授权。CAS客户端是指集成CAS协议的应用系统,用于与CAS服务器进行通信并实现单点登录功能。 以下是CAS客户端集成单点登录的代码示例: ```java // 引入CAS客户端依赖 <dependency> <groupId>org.jasig.cas.client</groupId> <artifactId>cas-client-core</artifactId> <version>3.6.0</version> </dependency> // 配置CAS客户端 <bean id="casClient" class="org.jasig.cas.client.authentication.CasClientAuthenticationFilter"> <property name="casServerLoginUrl" value="http://localhost:8081/cas/login" /> <property name="serverName" value="http://localhost:8080" /> </bean> // 配置CAS过滤器 <filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>http://localhost:8081/cas/login</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>http://localhost:8080</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> // 配置CAS单点登出过滤器 <filter> <filter-name>CAS Logout Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Logout Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> // 配置CAS请求单点登出过滤器 <filter> <filter-name>CAS Request Single Sign Out Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <filter-mapping> <filter-name>CAS Request Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ``` 以上代码是一个Java Web应用中集成CAS客户端的示例,通过配置CAS客户端和相关过滤器,实现与CAS服务器的通信和单点登录功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值