軟件是對質量的不懈追求

          Standalone Java CAS Client

          There's a variety of clients for CAS. The Java-based clients (JA-SIG, Yale, see JA-SIG website) typically handle the browser-based client interaction with CAS very well through ServletFilter implementations.

          Now what about programmatic authentication, i.e. achieving authentication through non-browser based applications? There exists a CAS .NET client but I did not manage to find the appropriate Java implementation. So here goes - it is based on the Apache HttpClient.

          In case I missed any existing implementation achieving the same purpose, let's look at the bright side: at least now I understand the CAS protocol :-)

          My CAS client works within any application. It uses the HttpClient and behaves like a browser client as CAS requires cookie support.

          Here's the code:
          import org.apache.commons.httpclient.Header;
          import org.apache.commons.httpclient.HttpClient;
          import org.apache.commons.httpclient.HttpMethod;
          import org.apache.commons.httpclient.HttpStatus;
          import org.apache.commons.httpclient.methods.GetMethod;
          import org.apache.commons.httpclient.methods.PostMethod;
          import org.apache.log4j.Logger;

          /**
          * The CasClient allows users to programmatically login
          * to CAS protected services based on the CAS 2 protocol.
          * This client behaves like a browser-client in terms of
          * cookie handling.<br>
          *
          @author Mathias Richter
          */
          public class CasClient
          {
            
             
          public static Logger LOG = Logger.getLogger( CasClient.class  );

             
          public static final String LOGIN_URL_PART = "login";
             
          public static final String SERVICE_VALIDATE_URL_PART = "serviceValidate";
             
          public static final String TICKET_BEGIN = "ticket=";
             
          private static final String LT_BEGIN = "name="lt" value="";
             public static final String CAS_USER_BEGIN = "<cas:user>";
             
          public static final String CAS_USER_END = "</cas:user>";
            
             
          private HttpClient fClient;
             
          private String fCasUrl;
            
             
          /**
              * Construct a new CasClient.
              *
              * 
          @param casUrl The base URL of the CAS service to be used.
              
          */
             
          public CasClient( String casBaseUrl )
             {
                 
          thisnew HttpClient(), casBaseUrl );
             }
            
             
          /**
              * Construct a new CasClient which uses the specified HttpClient
              * for its HTTP calls.
              *
              * 
          @param client
              * 
          @param casBaseUrl
              
          */
             
          public CasClient( HttpClient client, String casBaseUrl )
             {
                 fClient 
          = client;
                 fCasUrl 
          = casBaseUrl;
             }
            
             
          /**
              * Authenticate the specified username with the specified password.
              * This will not yield any ticket, as no service is authenticated
              * against. This wil just set the CAS cookie in this client upon
              * successful authentication.
              *
              * 
          @param username
              * 
          @param password
              
          */
             
          public void authenticate( String username, String password )
             {
                 authenticate( 
          null, username, password );
             }
            
             
          /**
              * Validate the specified service ticket against the specified service.
              * If the ticket is valid, this will yield the clear text user name
              * of the autenticated user.<br>
              * Note that each service ticket issued by CAS can be used exactly once
              * to validate.
              *
              * 
          @param serviceUrl
              * 
          @param serviceTicket
              *
              * 
          @return Clear text username of the authenticated user.
              
          */
             
          public String validate( String serviceUrl, String serviceTicket )
             {
                 String result 
          = null;
                 PostMethod method 
          = new PostMethod( fCasUrl + SERVICE_VALIDATE_URL_PART );
                 method.setParameter( 
          "service", serviceUrl );
                 method.setParameter( 
          "ticket", serviceTicket );
                 
          try
                 {
                     
          int statusCode = fClient.executeMethod(method);
                     
          if (statusCode != HttpStatus.SC_OK)
                     {
                         LOG.error( 
          "Could not validate: " + method.getStatusLine() );
                         method.releaseConnection();
                     } 
          else
                     {   
                         result 
          = extractUser( new String( method.getResponseBody() ) );
                     }
                 } 
          catch ( Exception x )
                 {
                     LOG.error( 
          "Could not validate: " + x.toString () );
                     x.printStackTrace();
                 }
                 method.releaseConnection();
                 
          return result;
             }
            
             
          /**
              * Authenticate the specified user with the specified password against the
              * specified service.
              *
              * 
          @param serviceUrl May be null. If a url is specified, the authentication will happen against this service, yielding a service ticket which can be validated.
              * 
          @param username
              * 
          @param password
              * 
          @return A valid service ticket, if and only if the specified service URL is not null.
              
          */
             
          public String authenticate( String serviceUrl, String username, String password )
             {
                 String lt 
          = getLt( serviceUrl );
                 
          if ( lt == null )
                 {
                     LOG.error( 
          "Cannot retrieve LT from CAS. Aborting authentication for '" + username + "'" );
                     
          return null;
                 }
                 String result 
          = null;
                 PostMethod method 
          = new PostMethod( fCasUrl + LOGIN_URL_PART );
                 
          if ( serviceUrl != null ) // optional
                     method.setParameter( "service", serviceUrl );
                 method.setParameter( 
          "_eventId""submit" );
                 method.setParameter(
          "username", username );
                 method.setParameter(
          "password", password );
                 method.setParameter(
          "lt", lt );
                 method.setParameter( 
          "gateway""true" );
                 
          try
                 {
                     fClient.executeMethod(method);
                     
          if ( serviceUrl == null )
                     {
                         
          if ( extractLt( new String( method.getResponseBody() ) ) != null ) // if CAS does not return a login page with an LT authentication was successful
                         {
                             LOG.error( 
          "Authentication for '" +  username + "' unsuccessful" );
                             
          if ( LOG.isDebugEnabled() )
                                 LOG.debug( 
          "Authentication for '" + username + "' unsuccessful." );
                         } 
          else
                         {
                             
          if ( LOG.isDebugEnabled() )
                                 LOG.debug( 
          "Authentication for '" + username + "' unsuccessful." );
                         }
                     } 
          else
                     {
                         Header h 
          = method.getResponseHeader( "Location" );
                         
          if ( h != null )
                             result 
          = extractServiceTicket( h.getValue() );
                         
          if ( result == null )
                             LOG.error( 
          "Authentication for '" + username + "' unsuccessful." );
                     }
                 } 
          catch ( Exception x )
                 {
                     LOG.error( 
          "Could not authenticate'" + username + "':" + x.toString () );
                 }
                 method.releaseConnection();
                 
          return result;
             }
            
             
          /**
              * Helper method to extract the user name from a "service validate" call to CAS.
              *
              * 
          @param data Response data.
              * 
          @return The clear text username, if it could be extracted, null otherwise.
              
          */
             
          protected String extractUser( String data )
             {
                 String user 
          = null;
                 
          int start = data.indexOf( CAS_USER_BEGIN  );
                 
          if ( start >= 0 )
                 {
                     start 
          += CAS_USER_BEGIN.length();
                     
          int end = data.indexOf( CAS_USER_END );
                     
          if ( end > start )
                         user 
          = data.substring( start, end );
                     
          else
                         LOG.warn( 
          "Could not extract username from CAS validation response. Raw data is: '" + data + "'" );
                 } 
          else
                 {
                     LOG.warn( 
          "Could not extract username from CAS validation response. Raw data is: '" + data + "'" );
                 }
                 
          return user;
             }
            
             
          /**
              * Helper method to extract the service ticket from a login call to CAS.
              *
              * 
          @param data Response data.
              * 
          @return The service ticket, if it could be extracted, null otherwise.
              
          */
             
          protected String extractServiceTicket( String data )
             {
                 String serviceTicket 
          = null;
                 
          int start = data.indexOf( TICKET_BEGIN  );
                 
          if ( start > 0 )
                 {
                     start 
          += TICKET_BEGIN.length();
                     serviceTicket 
          = data.substring( start );
                 }
                 
          return serviceTicket;
             }
            
             
          /**
              * Helper method to extract the LT from a login form from CAS.
              *
              * 
          @param data Response data.
              * 
          @return The LT, if it could be extracted, null otherwise.
              
          */
             
          protected String extractLt( String data )
             {
                 String token 
          = null;
                 
          int start = data.indexOf( LT_BEGIN  );
                 
          if ( start < 0 )
                 {
                     LOG.error( 
          "Could not obtain LT token from CAS: LT Token not found in response." );
                 } 
          else
                 {
                     start 
          += LT_BEGIN.length();
                     
          int end = data.indexOf( """, start );
                     token = data.substring( start, end );
                 }       
                 
          return token;
             }
            
             
          /**
              * This method requests the original login form from CAS.
              * This form contains an LT, an initial token that must be
              * presented to CAS upon sending it an authentication request
              * with credentials.<br>
              * If a service URL is provided (which is optional), this method
              * will post the URL such that CAS authenticates against the
              * specified service when a subsequent authentication request is
              * sent.
              *
              * 
          @param serviceUrl
              * 
          @return The LT token if it could be extracted from the CAS response.
              
          */
             
          protected String getLt( String serviceUrl )
             {
                 String lt 
          = null;
                 HttpMethod method 
          = null;
                 
          if ( serviceUrl == null )
                     method 
          = new GetMethod( fCasUrl + LOGIN_URL_PART );
                 
          else
                 {
                     method 
          = new PostMethod( fCasUrl + LOGIN_URL_PART );
                     ( ( PostMethod ) method ).setParameter( 
          "service", serviceUrl );
                 }
                 
          try
                 {
                     
          int statusCode = fClient.executeMethod(method);
                     
          if (statusCode != HttpStatus.SC_OK)
                     {
                         LOG.error( 
          "Could not obtain LT token from CAS: " + method.getStatusLine() );
                         method.releaseConnection();
                     } 
          else
                     {
                         Object o 
          = method.getResponseHeaders() ;
                         
          return extractLt( new String( method.getResponseBody() ) );
                     }
                 } 
          catch ( Exception x )
                 {
                     LOG.error( 
          "Could not obtain LT token from CAS: " + x.toString () );
                 }
                 method.releaseConnection();
                 
          return lt;
             }
            
          }

          posted on 2010-07-15 17:59 BlakeSu 閱讀(418) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 美姑县| 宁南县| 海晏县| 塘沽区| 台东市| 麻江县| 岚皋县| 齐齐哈尔市| 淮滨县| 桃园县| 吴桥县| 神木县| 台北县| 岐山县| 锡林浩特市| 泰兴市| 百色市| 常宁市| 宜良县| 武宁县| 伊川县| 凉城县| 额济纳旗| 芮城县| 海兴县| 南阳市| 满城县| 德昌县| 阿城市| 贡嘎县| 广德县| 阜康市| 福鼎市| 利川市| 沙田区| 徐州市| 余姚市| 瑞金市| 湘阴县| 乐陵市| 文昌市|