View Javadoc

1   /**
2    * Copyright (C) 2005-2009 Alfresco Software Limited.
3    *
4    * This file is part of the Spring Surf Extension project.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.springframework.extensions.webscripts.connector;
20  
21  import java.text.MessageFormat;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.json.JSONException;
26  import org.json.JSONObject;
27  import org.springframework.extensions.surf.exception.AuthenticationException;
28  import org.springframework.extensions.webscripts.json.JSONWriter;
29  
30  /**
31   * An implementation of an Alfresco ticket-based Authenticator.
32   * 
33   * This Authenticator can be plugged into a connector to allo the connector
34   * to handshake with an Alfresco Repository. This handshake involves POSTing
35   * the username and password to the /api/login WebScript.
36   * 
37   * A ticket is returned that is then plugged into a connector session.
38   * 
39   * @author muzquiano
40   * @author kevinr
41   */
42  public class AlfrescoAuthenticator extends AbstractAuthenticator
43  {
44      private static Log logger = LogFactory.getLog(AlfrescoAuthenticator.class);
45      
46      private static final String JSON_lOGIN = "'{'\"username\": \"{0}\", \"password\": \"{1}\"'}'";
47      private static final String API_LOGIN = "/api/login";
48      private static final String MIMETYPE_APPLICATION_JSON = "application/json";
49      
50      public final static String CS_PARAM_ALF_TICKET = "alfTicket";
51      
52      
53      /* (non-Javadoc)
54       * @see org.alfresco.connector.AbstractAuthenticator#authenticate(java.lang.String, org.alfresco.connector.Credentials, org.alfresco.connector.ConnectorSession)
55       */
56      public ConnectorSession authenticate(String endpoint, Credentials credentials, ConnectorSession connectorSession)
57              throws AuthenticationException
58      {
59          ConnectorSession cs = null;
60          
61          if (credentials != null)
62          {
63              // build a new remote client
64              RemoteClient remoteClient = new RemoteClient(endpoint);
65              
66              // retrieve the username and password
67              String user = (String) credentials.getProperty(Credentials.CREDENTIAL_USERNAME);
68              String pass = (String) credentials.getProperty(Credentials.CREDENTIAL_PASSWORD);
69              
70              if (logger.isDebugEnabled())
71                  logger.debug("Authenticating user: " + user);
72              
73              // POST to the login WebScript
74              remoteClient.setRequestContentType(MIMETYPE_APPLICATION_JSON);
75              String body = MessageFormat.format(JSON_lOGIN, JSONWriter.encodeJSONString(user), JSONWriter.encodeJSONString(pass));
76              Response response = remoteClient.call(API_LOGIN, body);
77              
78              // read back the ticket
79              if (response.getStatus().getCode() == 200)
80              {
81                  String ticket;
82                  try
83                  {
84                      JSONObject json = new JSONObject(response.getResponse());
85                      ticket = json.getJSONObject("data").getString("ticket");
86                  } 
87                  catch (JSONException jErr)
88                  {
89                      // the ticket that came back could not be parsed
90                      // this will cause the entire handshake to fail
91                      throw new AuthenticationException(
92                              "Unable to retrieve login ticket from Alfresco", jErr);
93                  }
94                  
95                  if (logger.isDebugEnabled())
96                      logger.debug("Parsed ticket: " + ticket);
97                  
98                  // place the ticket back into the connector session
99                  if (connectorSession != null)
100                 {
101                     connectorSession.setParameter(CS_PARAM_ALF_TICKET, ticket);
102                     
103                     // signal that this succeeded
104                     cs = connectorSession;
105                 }
106             }
107             else
108             {
109                 if (logger.isDebugEnabled())
110                     logger.debug("Authentication failed, received response code: " + response.getStatus().getCode());            
111             }
112         }
113         else if (logger.isDebugEnabled())
114         {
115             logger.debug("No user credentials available - cannot authenticate.");
116         }
117         
118         return cs;
119     }
120     
121     /* (non-Javadoc)
122      * @see org.alfresco.connector.AbstractAuthenticator#isAuthenticated(java.lang.String, org.alfresco.connector.ConnectorSession)
123      */
124     public boolean isAuthenticated(String endpoint, ConnectorSession connectorSession)
125     {
126         return (connectorSession.getParameter(CS_PARAM_ALF_TICKET) != null);
127     }
128 }