View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.client.bindings.spi;
20  
21  import java.net.Authenticator;
22  import java.net.PasswordAuthentication;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  import org.w3c.dom.Element;
29  
30  /**
31   * NTLM authentication provider class. USE WITH CARE! DO NOT USE IN PRODUCTION!
32   * 
33   * <p>
34   * <b>The combination of CMIS and NTLM is not suited for production. Choose a
35   * different authentication method!</b>
36   * </p>
37   * 
38   * <p>
39   * This authentication provider sets a {@link java.net.Authenticator} which
40   * replaces the current authenticator, if any. It will fail if this
41   * authenticator is replaced later by another part of the code.
42   * </p>
43   * 
44   * <p>
45   * Since {@link java.net.Authenticator} is a system-wide authenticator, <b>it
46   * does not reliably work in multi-user environments</b>! To achieve that you
47   * have to wrap OpenCMIS into its own class loader.
48   * </p>
49   * 
50   * <p>
51   * This authenticator only works reliably for read operations (except queries).
52   * Write operations and queries may work for a while but will eventually fail.
53   * </p>
54   */
55  public class NTLMAuthenticationProvider extends AbstractAuthenticationProvider {
56  
57      private static final long serialVersionUID = 1L;
58  
59      private static final Logger LOG = LoggerFactory.getLogger(NTLMAuthenticationProvider.class);
60  
61      // java.net.Authenticator is static, so this can be static too
62      private static final OpenCMISAuthenticator AUTHENTICATOR = new OpenCMISAuthenticator();
63      static {
64          Authenticator.setDefault(AUTHENTICATOR);
65      }
66  
67      @Override
68      public void setSession(BindingSession session) {
69          super.setSession(session);
70          LOG.warn("Use NTLM only for testing! Choose a different authentication method in production.");
71      }
72  
73      @Override
74      public Map<String, List<String>> getHTTPHeaders(String url) {
75          // get user and password
76          String user = getUser();
77          String password = getPassword();
78  
79          // if no user is set, reset the authenticator
80          if (user == null) {
81              AUTHENTICATOR.reset();
82              return null;
83          }
84  
85          if (password == null) {
86              password = "";
87          }
88  
89          // set user and password
90          AUTHENTICATOR.setPasswordAuthentication(user, password);
91  
92          // OpenCMIS is not in charge of the authentication
93          // -> no HTTP header to set
94          return null;
95      }
96  
97      @Override
98      public Element getSOAPHeaders(Object portObject) {
99          // no SOAP headers to set
100         return null;
101     }
102 
103     /**
104      * OpenCMIS Authenticator class.
105      */
106     static class OpenCMISAuthenticator extends Authenticator {
107 
108         private PasswordAuthentication passwordAuthentication;
109 
110         /**
111          * Resets the user and password. The next request will not be
112          * authenticated.
113          */
114         public synchronized void reset() {
115             passwordAuthentication = null;
116         }
117 
118         /**
119          * Sets a new user and password.
120          */
121         public synchronized void setPasswordAuthentication(String user, String password) {
122             passwordAuthentication = new PasswordAuthentication(user, password.toCharArray());
123         }
124 
125         @Override
126         protected synchronized PasswordAuthentication getPasswordAuthentication() {
127             return passwordAuthentication;
128         }
129     }
130 }