CAS之客户端使用——基于CAS的单点登陆的研究(下)

前言

上一篇主要讲述了CAS的Server端的配置和使用,点击这里进行回顾。这篇则讲述CAS的客户端的使用,主要是JAVA客户端以及RESTFUL接口

一、为WEB应用配置CAS认证

1.给WEB应用所部署的Servlet容器打证书

上一篇中讲过,使用HTTPS通信,做过一个证书库。这里还需要使用它。如果不是用HTTPS,就不用这一步了。

caserver  生成的 tomcat.keystore 导出一个子认证. 然后这个子认证要导入到java 单点客户端jdk认证库里. 这样子系统与单点服务系统建立了验证关系.  当然如果单点服务与单点客户端在同一台机器上,共用一个jdk,就不存在这个证书的导入与验证了.

导出证书
keytool -export -file myserver.cert -alias tomcat -keystore tomcat.keystore

 

将认证导入到jdk认证库cacerts中

keytool -import -trustcacerts -alias javacas -file "D:/Program Files/Apache Software Foundation/Tomcat 6.0/conf/myserver.cert" -keypass 123456  -keystore "%JAVA_HOME%/jre/lib/security/cacerts"

cacerts是java默认的认证库,默认密码为:changeit

 2.修改WEB应用

(参考官方例子)

增加CAS Client到客户应用

增加所需的cas-client-core包,当前版本是3.1.10.可以直接下载拷贝到WEB-INF/lib,

使用maven可以加入以下代码

<dependency>
<groupId>org.jasig.cas</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.1.10</version>
</dependency>

 可能还需要加入一些其他常用的包,根据需要来添加。

 修改web.xml

增加:

<context-param>
        <param-name>serverName</param-name>
        <param-value>http://localhost:8080</param-value>
    </context-param>

  <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://wzfedora:8080/cas-server-webapp/login</param-value>
        <param-value>https://wzfedora:8443/cas-server-webapp/login</param-value>
          -->
        <param-value>http://10.1.81.235/cas/login</param-value>
    </init-param>
    
  </filter>
   
  <filter>
    <filter-name>CAS Validation Filter</filter-name>
    <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
    <init-param>
        <param-name>casServerUrlPrefix</param-name>
        <param-value>http://10.1.81.235/cas</param-value>
        <!--  
        <param-value>https://wzfedora:8443/cas-server-webapp</param-value>
        <param-value>http://wzfedora:8080/cas-server-webapp</param-value>
        -->
    </init-param>
  </filter>
   
  <filter>
    <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
    <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
  </filter>
   
    <filter-mapping>
        <filter-name>CAS Authentication Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
     
    <filter-mapping>
        <filter-name>CAS Validation Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
     
    <filter-mapping>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

说明:

这里配置了3个过滤器,分别用来验证、认证和附加一些信息(如登录者的信息等)

  • CAS Validation Filter 其中的Cas20ProxyReceivingTicketValidationFilter的20表示使用CAS 2.0协议
  • CAS Authentication Filter
  • CAS HttpServletRequest Wrapper Filter
 
 

另外,如果使用HTTPS,似乎必须使用域名,用IP则会出错。若是HTTP,则不影响。

二、客户端调用REST接口

CAS Server端配置REST支持已经再上篇中讲述了,点这里查看。官方的地址请点击这里。

再RESTFul中,TGT被暴露当作资源,拥有唯一的URI. The RESTful API follows the same basic protocol as the original CAS2 protocol

 RESTful API遵循CAS2基础协议.

下面是一个JAVA客户端调用的例子

import java.io.IOException;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
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 <a
 * href="http://www.ja-sig.org/wiki/display/CASUM/RESTful+API">wiki</a>.
 *
 * @author <a href="mailto:[email protected]">jesse lauren farinacci</a>
 * @since 3.4.2
 */
public final class Client
{
  private static final Logger LOG = Logger.getLogger(Client.class.getName());
 
  private Client()
  {
    // static-only access
  }
 
  public static String getTicket(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(server, getTicketGrantingTicket(server, username,
        password), service);
  }
 
  private static String getServiceTicket(final String server,
      final String ticketGrantingTicket, final String service)
  {
    if (ticketGrantingTicket == null)
      return null;
 
    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;
  }
 
  private static String getTicketGrantingTicket(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);
  }
 
  public static void main(final String[] args)
  {
    final String server = "http://10.1.81.235/cas/v1/tickets";
    final String username = "admin";
    final String password = "admin123";
    final String service = "http://localhost:8080/casclientweb";
 
    LOG.info(getTicket(server, username, password, service));
  }
}

运行结果如下

2012-4-11 16:05:48 Client main
信息: ST-4-J0IQnprd2DhJlku059gw-cas

你可能感兴趣的:(CAS之客户端使用——基于CAS的单点登陆的研究(下))