首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

构建和实现单点登录解决方案-Active Directory Server 身份验证

构建和实现单点登录解决方案-Active Directory Server 身份验证

Active Directory Server 身份验证在我的教育门户项目中,可以很轻松地修改应用程序,因为我能够得到源代码。我在每个应用程序中使用了 servlet 过滤器。在这种情况下,当用户首次访问门户并请求一个受限制的应用程序或数据源时,CAS 将执行身份验证。身份验证成功之后,CAS servlet 过滤器可以检查 ticket,并将用户名作为参数传递给请求的应用程序。我修改了现有的应用程序登录屏幕,让它们在成功的身份验证之后从 CAS 接收用户名参数。然后,应用程序可以使用这个参数对用户进行授权,并对用户的活动进行审计记录。
但是,CAS 本身没有附带任何真正有用的身份验证器。默认的身份验证器仅仅检查用户名和密码是否相同。在教育门户项目中,我使用 Microsoft 的 Active Directory Server 存储用户的个人信息。所以我需要扩展 CAS 服务器,让它根据 Active Directory Server 检查用户名和密码。
Yale University 的 CAS 设计人员开发了一个可插入的身份验证器架构。通过扩展 PasswordHandler 接口,开发人员可以创建一个类来实现密码检查逻辑。
清单 2. CAS 的可插入身份验证器架构
1
2
3
4
5
6
7
8
9
10
11
12
/** Interface for password-based authentication handlers. */
public interface PasswordHandler extends AuthHandler {

  /**
   * Authenticates the given username/password pair, returning true
   * on success and false on failure.
   */
  boolean authenticate(javax.servlet.ServletRequest request,
                       String username,
                       String password);

}




我要做的只是了解如何使用 Active Directory Server 检查用户名和密码,创建一个类来扩展这个接口,并添加执行身份验证的代码。
ADS 是一种与 LDAP3 兼容的目录服务器。它支持许多不同的身份验证方法,主要包括匿名(anonymous)简单(simple)SASL(Simple Authentication and Security Layer)。匿名身份验证不适合我的项目;简单身份验证用明文发送密码,这也不满足需要。所以我使用 SASL。
SASL 支持可插入的身份验证。这意味着可以对 LDAP 客户机和服务器进行配置,让它们相互协商并使用多种身份验证机制之一。下面是当前定义的一部分 SASL 机制:
  • Anonymous
  • CRAM-MD5
  • Digest-MD5
  • External
  • Kerberos V4
  • Kerberos V5
  • SecurID
  • Secure Remote Password
  • S/Key
  • X.509
在这些机制中,流行的 LDAP 服务器(比如 Sun、OpenLDAP 和 Microsoft 提供的服务器)都支持 External、Digest-MD5 和 Kerberos V5。
CAS 本身与 Kerberos 相似,它们有许多相同的概念,比如 ticket 和 ticket-granting ticket(在 CAS 中实际上称为 ticket-granting cookie),它们的协议也是相似的。所以,选择 Kerberos 机制似乎是很自然的。另外,添加对 Kerberos 身份验证的支持让 CAS 在未来的开发中能够作为基于 Web 的 Kerberos 代理代表用户,这使 CAS 能够替用户管理 Kerberos ticket 的所有方面。这意味着远程用户也可以使用相同的 Kerberos 身份验证机制访问本地和网络资源。
Kerberos 协议已经内置在 ADS 和 Windows 2000/XP 中。Java Authentication and Authorization Service(JAAS)提供了 Kerberos Login Module 的一个实现(参考资料 中列出的一个教程详细描述了如何建立一个示例应用程序)。精确地说,它是 GSS-API SASL 机制,但是它只为 LDAP3 服务器提供 Kerberos v5 身份验证。
Kerberos 身份验证是一个很简单的过程(如果仔细地按照以下说明进行操作的话):
  • 在 JAAS 配置文件中为应用程序类配置 Login Module。
    1
    2
    3
    4
    edu.yale.its.tp.cas.auth.provider.KerberosAuthHandler  
    {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE;
    };




  • 创建一个 LoginContext,传递执行身份验证的类的名称和 CallBackHandler 对象。
    1
    2
    LoginContext lc = new LoginContext(CASApp.class.getName(),
                        new CASCallbackHandler());




  • 调用 login() 方法来执行身份验证。如果执行过程没有异常,身份验证就成功了。如果抛出了异常,那么这个异常会指出失败的原因。
要想深入了解 Kerberos 身份验证,建议您利用本文末尾的参考资料。(我还提供了自己的实现和配置文件,KerberosAuthHandler 和 CASCallBackHandler。)
需要创建一个新的 PasswordHandler 实现,KerberosAuthHandler,它按照上面的方法根据使用 Kerberos v5 的 Active Directory Server 进行身份验证。
清单 3. 创建新的 PasswordHandler 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class KerberosAuthHandler implements PasswordHandler {

  public boolean authenticate(javax.servlet.ServletRequest request,
                                String username,
                                String password)
  {

    LoginContext lc = null;
     
    try
    {
    /* Set up the Callback handler, and initialise */
/* the userid and password fields */

       CASCallbackHandler ch = new CASCallbackHandler();
       ch.setUserId(username);
       ch.setPassword(password);
         
       /* Initialise the login context - LoginModule configured */
       /* in cas_jaas.conf and */
              /* set to use Krb5LoginModule. */
       lc = new LoginContext(KerberosAuthHandler.class.getName(), ch);

       /* Perform the authentication */
       lc.login();

    }
    catch (LoginException le)
    {
     System.err.println("Authentication attempt failed" + le);
     return false;
    }
    return true;

  }
}




在创建 LoginContext 时,传递这个类名和 CASCallbackHandler 对象。JAAS 配置文件指定这个类使用的登录模块。
在调用 login() 方法时,登录模块知道为了进行身份验证它需要从用户/应用程序获得哪些信息。在使用 Kerberos 时,它需要用户名和密码,所以它构造一个数组,其中包含两个回调对象(NameCallback 和 PasswordCallback),然后调用 CallbackHandler 对象,这个对象决定如何执行这些回调并获得用户名和密码。
我采用最简单最有利的方式,使用 CallbackHandler 上的 setter 方法显式地设置用户 ID 和密码。然后,CallbackHandler 将它们传递给 NameCallback 和 PasswordCallback 对象。
清单 4. 用 setName (CASUserId) 和 setPassword (CASPassword) 设置 ID 和密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class CASCallbackHandler implements CallbackHandler
{

    private String CASUserId;
    private char [] CASPassword;

    public void handle(Callback[] callbacks)
    throws java.io.IOException, UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
        if (callbacks instanceof NameCallback) {
            NameCallback cb = (NameCallback)callbacks;
            cb.setName(CASUserId);

        } else if (callbacks instanceof PasswordCallback) {
            PasswordCallback cb = (PasswordCallback)callbacks;
            cb.setPassword(CASPassword);

        } else {
            throw new UnsupportedCallbackException(callbacks);
        }
        }
    }

    public void setUserId(String userid)
    {
    CASUserId = userid;
    }

    public void setPassword(String password)
    {
    CASPassword = new char[password.length()];
    password.getChars(0, CASPassword.length, CASPassword, 0);
    }




下面要做的是让 CAS 使用新的身份验证处理器。方法是在 webapps/cas 中 CAS 服务器的 web.xml 文件中进行以下设置:
清单 5. 让 CAS 使用新的身份验证处理器
1
2
3
4
5
6
7
<!-- Authentication handler -->
    <context-param>
        <param-name>edu.yale.its.tp.cas.authHandler</param-name>
        <param-value>
             edu.yale.its.tp.cas.auth.provider.KerberosAuthHandler
        </param-value>
    </context-param>




ZIP 文件( 中的 KerberosAuthSrc.zip)中包含一个 web.xml 示例。
必须重新启动 Tomcat,但是这一次还需要设置一些 Java 运行时属性。对 ZIP 文件(KerberosAuthSrc.zip)进行解压,并将文件 cas_jaas.conf、krb5.conf 和 setkerberosjvmoptions.bat 复制到 TOMCAT_HOME 目录中。运行 setkerberosjvmoptions.bat,然后启动 Tomcat。
现在,可以再用 HelloWorld 应用程序做实验了。这一次,可以使用 Active Directory Server 中定义的有效的 Kerberos 用户名和密码对。
返回列表