View Javadoc
1   /* 
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    * http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   *
14   */
15  
16  package org.esigate.authentication;
17  
18  import java.util.Properties;
19  
20  import org.apache.http.HttpRequest;
21  import org.apache.http.HttpResponse;
22  import org.apache.http.util.EntityUtils;
23  import org.esigate.Driver;
24  import org.esigate.HttpErrorPage;
25  import org.esigate.events.Event;
26  import org.esigate.events.EventDefinition;
27  import org.esigate.events.EventManager;
28  import org.esigate.events.IEventListener;
29  import org.esigate.events.impl.FragmentEvent;
30  import org.esigate.events.impl.ProxyEvent;
31  import org.esigate.extension.Extension;
32  import org.esigate.http.IncomingRequest;
33  import org.esigate.http.OutgoingRequest;
34  
35  /**
36   * This class is an adapter from the old ESIgate 2.X/3.X API used for AuthentificationHandlers to the new extension
37   * systems.
38   * 
39   * <p>
40   * The following events are mapped on init :
41   * <uL>
42   * <li> {@link EventManager#EVENT_PROXY_PRE} is mapped to {@link #beforeProxy(HttpRequest)}</li>
43   * <li>{@link EventManager#EVENT_FRAGMENT_PRE} is mapped to {@link #preRequest(OutgoingRequest, IncomingRequest)}</li>
44   * <li> {@link EventManager#EVENT_FRAGMENT_POST} is mapped to
45   * {@link #needsNewRequest(HttpResponse, OutgoingRequest, IncomingRequest)}</li>
46   * </ul>
47   * 
48   * <p>
49   * To update an old AuthentificationHandler :
50   * <ul>
51   * <li>Remote "implements AuthentificationHandler" from class definition</li>
52   * <li>Add "extends GenericAuthentificationHandler" to class definition</li>
53   * </ul>
54   * 
55   * @author Nicolas Richeton
56   * 
57   */
58  public abstract class GenericAuthentificationHandler implements IEventListener, Extension {
59  
60      private Driver driver;
61  
62      /**
63       * Method called before proxying a request
64       * 
65       * This method can ask the users credentials by sending an authentication page or a 401 code or redirect to a login
66       * page. If so the method must return false in order to stop further processing.
67       * 
68       * @param httpRequest
69       *            the incoming request
70       * @return true if the processing must continue, false if the response has already been sent to the client.
71       */
72      public abstract boolean beforeProxy(HttpRequest httpRequest);
73  
74      /**
75       * Method called before sending a request to the destination server.
76       * 
77       * This method can be used to add user credentials to the request
78       * 
79       * @param outgoingRequest
80       * @param incomingRequest
81       */
82      public abstract void preRequest(OutgoingRequest outgoingRequest, IncomingRequest incomingRequest);
83  
84      /**
85       * Method called after the response has been obtained from the destination server.
86       * 
87       * This method can be used to ask for a new request if the destination server uses a challenge-based authentication
88       * mechanism with an arbitrary number of steps.
89       * 
90       * @param response
91       * @param outgoingRequest
92       * @param incomingRequest
93       * @return true if a new request is needed
94       */
95      public abstract boolean needsNewRequest(HttpResponse response, OutgoingRequest outgoingRequest,
96              IncomingRequest incomingRequest);
97  
98      /*
99       * (non-Javadoc)
100      * 
101      * @see org.esigate.extension.Extension#init(org.esigate.Driver, java.util.Properties)
102      */
103     @Override
104     public final void init(Driver d, Properties properties) {
105         this.driver = d;
106         this.driver.getEventManager().register(EventManager.EVENT_PROXY_PRE, this);
107         this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_PRE, this);
108         this.driver.getEventManager().register(EventManager.EVENT_FRAGMENT_POST, this);
109 
110         init(properties);
111     }
112 
113     public abstract void init(Properties properties);
114 
115     @Override
116     public boolean event(EventDefinition id, Event event) {
117 
118         if (EventManager.EVENT_FRAGMENT_PRE.equals(id)) {
119             FragmentEvent e = (FragmentEvent) event;
120             preRequest(e.getHttpRequest(), e.getOriginalRequest());
121         } else if (EventManager.EVENT_FRAGMENT_POST.equals(id)) {
122             FragmentEvent e = (FragmentEvent) event;
123 
124             while (needsNewRequest(e.getHttpResponse(), e.getHttpRequest(), e.getOriginalRequest())) {
125                 EntityUtils.consumeQuietly(e.getHttpResponse().getEntity());
126                 preRequest(e.getHttpRequest(), e.getOriginalRequest());
127                 try {
128                     e.setHttpResponse(this.driver.getRequestExecutor().execute(e.getHttpRequest()));
129                 } catch (HttpErrorPage e1) {
130                     e.setHttpResponse(e1.getHttpResponse());
131                 }
132             }
133         } else if (EventManager.EVENT_PROXY_PRE.equals(id)) {
134             ProxyEvent e = (ProxyEvent) event;
135             e.setExit(!beforeProxy(e.getOriginalRequest()));
136         }
137 
138         return true;
139     }
140 
141     public Driver getDriver() {
142         return driver;
143     }
144 }