CAS 使用 Windows AD 验证用户单点登录

Yale CAS在最简单的安装下,对用户和密码只做相同性匹配的认证,当然在CAS Server源代码中也包含了其它认证方式的实例,开发者可以通过实现PasswordHandler接口来使用其它的认证方式,如数据库用户的用户名和密码匹配认证,数字签名的验证,操作系统用户认证,以及LDAP用户认证等模式。下面这段文章介绍了使用Windows Active Directory中的用户信息对CAS用户做验证的简单实例。

Active Directory Server authentication

In my educational portal project, the applications can be easily modified because the source code is available. I have used the servlet filter for each of these applications. In this case, CAS will perform the authentication when the user first visits the portal and requests a restricted application or data source. Once authentication is successful, the CAS servlet filter can validate the ticket and pass the username as a parameter to the requested application. I have modified the existing application login screens to accept the username parameter from CAS after a successful authentication. The applications can then use this parameter to authorize users and provide an audit trail of user activity.

Unfortunately, CAS does not come with any truly useful authenticators. The default authenticator simply verifies that the username and password are identical. In the educational portal project I use Microsoft's Active Directory Server to store the user profiles. So I needed to extend the CAS server to authenticate the username and password against the Active Directory Server.

The creators of CAS at Yale University have developed a pluggable authenticator architecture. By extending the PasswordHandler interface, a developer can create a class to implement the password-checking logic.

Listing 2. CAS's pluggable authenticator architecture

/** 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);
  }

All I had to do was find out how to check the username and password using Active Directory Server, create a class to extend this interface, and add the code to perform the authentication.

ADS is an LDAP3-compliant directory server. It supports a number of different authentication methods, the principal ones being anonymous, simple, and SASL (Simple Authentication and Security Layer). Anonymous authentication is of no use in this instance; simple authentication sends the password as cleartext, again not suitable for these needs. So SASL is the option I will use.

SASL supports pluggable authentication. This means that you can configure the LDAP client and server to negotiate and use any of a range of mechanisms. The following are some of the currently defined SASL mechanisms:

  • Anonymous
  • CRAM-MD5
  • Digest-MD5
  • External
  • Kerberos V4
  • Kerberos V5
  • SecurID
  • Secure Remote Password
  • S/Key
  • X.509

Of these mechanisms, popular LDAP servers (such as those from Sun, OpenLDAP, and Microsoft) support External, Digest-MD5, and Kerberos V5.

CAS itself is Kerberos-like, sharing many of the same concepts such as tickets, ticket-granting tickets (actually called ticket-granting cookies in CAS), and a similar protocol. So choosing this mechanism felt like a natural fit. Also adding support for Kerberos authentication will enable CAS, in a future development, to act as a Web-based Kerberos agent on behalf of the user, allowing CAS to manage all aspects of Kerberos tickets for its users. This would mean that the same Kerberos authentication mechanisms used to access local and network resources could also be used by remote users.

The Kerberos protocol is already built into ADS and Windows 2000/XP. The Java Authentication and Authorization Service (JAAS) provides an implementation of a Kerberos Login Module (see Resources for the tutorial that provides detail on how to get a sample application running). To be precise, it is GSS-API SASL mechanism that you will use, but this only supports Kerberos v5 authentication to LDAP3 servers.

Kerberos authentication is a straightforward process (assuming you follow the instructions carefully):

1. Configure the Login Module for your application class in your JAAS configuration file.

    edu.yale.its.tp.cas.auth.provider.KerberosAuthHandler 
    {
        com.sun.security.auth.module.Krb5LoginModule required client=TRUE;
    };

2. Create a LoginContext, passing the name of the class doing the authentication, and a CallBackHandler object.

    LoginContext lc = new LoginContext(CASApp.class.getName(),
                    new CASCallbackHandler());

3. Call the login() method to perform the authentication. If this executes without exceptions, then authentication is successful. If an exception is thrown, then the exception indicates the cause of the failure.

For a more in-depth look at Kerberos authentication, I suggest you use the resources at the end of the article. (I've also provided a download of my implementation and configuration files, KerberosAuthHandler and CASCallBackHandler.)

You need to create a new PasswordHandler implementation, the KerberosAuthHandler, which uses the above methods to authenticate against the Active Directory Server using Kerberos v5.

Listing 3. Creating the new PasswordHandler implementation

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;

  }
}

When the LoginContext is created, I pass the classname and the CASCallbackHandler object. The JAAS configuration file specifies the login module to use for this class.

When the login() method is called, the login module knows what information it needs from the user/application in order to authenticate them. In the case of Kerberos, it needs a username and password, so it constructs an array of two callback objects (NameCallback and PasswordCallback) and then calls the CallbackHandler object, which decides how it should perform these callbacks and retrieve the username and password.

I have taken the simplest and most expedient route and explicitly set the user ID and password using setter methods on the CallbackHandler. Then the CallbackHandler simply passes these on to the NameCallback and PasswordCallback objects.

Listing 4. Setting ID and password with setName (CASUserId) and setPassword (CASPassword)

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[i] instanceof NameCallback) {
        NameCallback cb = (NameCallback)callbacks[i];
        cb.setName(CASUserId);

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

    } else {
        throw new UnsupportedCallbackException(callbacks[i]);
    }
      }
    }

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

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

The next thing to do is tell CAS to use the new authentication handler. Do this by setting the following in the web.xml file for the CAS server in webapps/cas:

Listing 5. Telling CAS to use the new authentication handler

<!-- 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>

An example web.xml is included in the ZIP file (KerberosAuthSrc.zip in Resources).

You'll have to restart Tomcat, but this time you'll also need to set some Java runtime properties . Expand the ZIP file (KerberosAuthSrc.zip) and copy the files cas_jaas.conf, krb5.conf, and setkerberosjvmoptions.bat to the TOMCAT_HOME directory. Run the setkerberosjvmoptions.bat and then start Tomcat.

Now you are ready to repeat the HelloWorld experiment. This time you can use a valid Kerberos username and password pair as defined in your Active Directory Server.

Single sign-off

Without a unified strategy, developers re-implement custom security for each network application. This can result in a variety of scalability and maintenance problems. Single sign-on solutions can be that unified framework for security and authentication, alleviating much of the burden on users, administrators, and developers.

The concept of single sign-on, the technologies, and the implications for users and administrators are complex, so I have only scratched the surface in this article. But I have provided you with some practical ways to implement a single sign-on scheme using the proven CAS application from Yale University, and have also detailed a method to extend this technology so you can use it to authenticate users to a LDAP server (specifically, to an Active Directory Server using the Kerberos protocol).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值