CAS环境搭建完成之后,由于项目中需要模拟CAS登陆并获取相应的TICKET,专门学习了一下RESTFUL API的使用。

以下例子代码实现的功能是模拟登陆CAS,生成ST为各个集成了CAS的应用使用。

将RESTFUL API的调用封装到了一个类中:

package com.feiquan16.cas.util;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
/**
 * An example Java client to authenticate against CAS using REST services.
 * Please ensure you have followed the necessary setup found on the wiki.
 *
 * @author jesse lauren farinacci
 * @since 3.4.2
 */
public final class CASUtility {
    private static final Logger LOG = Logger.getLogger(CASUtility.class.getName());
    public static PropertiesReader pr = null;
    private CASUtility() {
        // static-only access
    }
    public static String getTicket(final HttpServletRequest request,
            final HttpServletResponse response, final String server,
            final String username, final String password, final String service) {
                notNull(server, "server must not be null");
                notNull(username, "username must not be null");
                notNull(password, "password must not be null");
                notNull(service, "service must not be null");
        return getServiceTicket(request, response, server, getTicketGrantingTicket(response, server, username, password), service);
    }
    private static String getServiceTicket(final HttpServletRequest request,
            final HttpServletResponse res, final String server,
            final String ticketGrantingTicket, final String service) {
        if (ticketGrantingTicket == null)
            return null;
        res.setHeader("P3P","CP=CAO PSA OUR");
                                                                     
        String broswer = "";
        try {
            String agent = request.getHeader("User-Agent");
            StringTokenizer st = new StringTokenizer(agent,";");
            st.nextToken();
            broswer = st.nextToken();
            LOG.info("User's Browser is "+broswer);
        }catch(Exception e) {
            LOG.info("Fail to get User's Browser Type.");
        }
                                                                     
        LOG.info("ticketGrantingTicket : " + ticketGrantingTicket);
        Cookie c1 = new Cookie("CASTGC", ticketGrantingTicket);
                                                                     
        pr = PropertiesReader.getInstance("");
        String domain = pr.getPropertiy("cas.server.domain");
        if (broswer != null && broswer.trim().startsWith("MSIE")){
            c1.setDomain(domain);
            c1.setPath("/");
        } else {
            c1.setDomain(domain);
            c1.setPath("/cas/");
        }
        res.addCookie(c1);
        final HttpClient client = new HttpClient();
        final PostMethod post = new PostMethod(server + "/" + ticketGrantingTicket);
        post.setRequestBody(new NameValuePair[] { new NameValuePair("service", service) });
        try {
            client.executeMethod(post);
            final String response = post.getResponseBodyAsString();
            switch (post.getStatusCode()) {
            case 200:
                return response;
            default:
                LOG.warning("Invalid response code (" + post.getStatusCode() + ") from CAS server!");
                LOG.info("Response (1k): " + response.substring(0, Math.min(1024, response.length())));
                break;
            }
        } catch (final IOException e) {
            LOG.warning(e.getMessage());
        } finally {
            post.releaseConnection();
        }
        return null;
    }
    public static String getTicketGrantingTicket(final HttpServletResponse res,
            final String server, final String username, final String password) {
        final HttpClient client = new HttpClient();
        final PostMethod post = new PostMethod(server);
        post.setRequestBody(new NameValuePair[] {
                new NameValuePair("username", username),
                new NameValuePair("password", password) });
        try {
            client.executeMethod(post);
            final String response = post.getResponseBodyAsString();
            switch (post.getStatusCode()) {
            case 201: {
                final Matcher matcher = Pattern.compile(".*action=\".*/(.*?)\".*").matcher(response);
                if (matcher.matches())
                    return matcher.group(1);
                LOG.warning("Successful ticket granting request, but no ticket found!");
                LOG.info("Response (1k): " + response.substring(0, Math.min(1024, response.length())));
                break;
            }
            default:
                LOG.warning("Invalid response code (" + post.getStatusCode() + ") from CAS server!");
                LOG.info("Response (1k): " + response.substring(0, Math.min(1024, response.length())));
                break;
            }
        }
        catch (final IOException e) {
            LOG.warning(e.getMessage());
        }
        finally {
            post.releaseConnection();
        }
        return null;
    }
    private static void notNull(final Object object, final String message) {
        if (object == null)
            throw new IllegalArgumentException(message);
    }
}

然后新建了一个servlet去调用上门这个类生成TICKET。

package com.feiquan16.cas.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.feiquan16.cas.util.CASUtility;
import com.feiquan16.cas.util.PropertiesReader;
public class CASTicketServlet extends HttpServlet {
                                                                   
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    public static PropertiesReader pr = null;
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{
        PrintWriter writer = response.getWriter();
        response.setContentType("text/html");
                                                                       
        pr = PropertiesReader.getInstance("");
        System.out.println("----------");
        String server = pr.getPropertiy("cas.service.url");
                                                                       
        String username = "b";request.getParameter("username");
                                                                       
        String password = "b";request.getParameter("ObSSOCookie");
        String service = "http://andrew.biz.com:9080/HRDemo";request.getParameter("service");
                                                                       
        response.setHeader("P3P","CP=CAO PSA OUR");
        System.out.println("----------");
        String ticket = CASUtility.getTicket(request,response, server, username, password, service);
                                                                       
        System.out.println(ticket);
                                                                       
        response.sendRedirect(service);
        writer.print(ticket);
    }
                                                                   
    public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{
        this.doGet(request, response);
    }
                                                                   
}

上面代码39行,将会跳转到应用HRDemo,这个HRDemo是被CAS保护的。


注意要模拟该场景至少需要2个web应用和一个cas服务端。这2个web应用中模拟生成ticket的应用不需要被CAS保护。另外,这个2个web应用需要在同一域中。