1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/AuthRequestHandler.java,v 1.1 2004/11/20 17:56:40 olegk Exp $
3    * $Revision: 155418 $
4    * $Date: 2005-02-26 08:01:52 -0500 (Sat, 26 Feb 2005) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 1999-2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient.server;
31  
32  import java.io.IOException;
33  
34  import org.apache.commons.httpclient.Credentials;
35  import org.apache.commons.httpclient.Header;
36  import org.apache.commons.httpclient.HttpStatus;
37  import org.apache.commons.httpclient.UsernamePasswordCredentials;
38  import org.apache.commons.httpclient.auth.BasicScheme;
39  
40  /***
41   * This request handler guards access to the http server when used in a request handler
42   * chain. It checks the headers for valid credentials and performs the
43   * authentication handshake if necessary.
44   * 
45   * @author Ortwin Glueck
46   * @author Oleg Kalnichevski
47   */
48  public class AuthRequestHandler implements HttpRequestHandler {
49      
50      private Credentials credentials = null;
51      private String realm = null;
52      private boolean keepalive = true;
53  
54      /***
55       * The authenticate response header.
56       */
57      public static final String AUTH_RESP = "Authorization";
58  
59      /***
60       * TODO replace creds parameter with a class specific to an auth scheme
61       * encapsulating all required information for a specific scheme
62       * 
63       * @param creds
64       */
65      public AuthRequestHandler(final Credentials creds, final String realm, boolean keepalive) {
66          if (creds == null)
67              throw new IllegalArgumentException("Credentials may not be null");
68          this.credentials = creds;
69          this.keepalive = keepalive;
70          if (realm != null) {
71              this.realm = realm;
72          } else {
73              this.realm = "test";
74          }
75      }
76  
77      public AuthRequestHandler(final Credentials creds, final String realm) {
78          this(creds, realm, true);
79      }
80      
81      public AuthRequestHandler(final Credentials creds) {
82          this(creds, null, true);
83      }
84      
85      public boolean processRequest(
86          final SimpleHttpServerConnection conn,
87          final SimpleRequest request) throws IOException
88      {
89          Header clientAuth = request.getFirstHeader(AUTH_RESP);
90          if (clientAuth != null && checkAuthorization(clientAuth)) {
91              return false;
92          } else {
93              SimpleResponse response = performBasicHandshake(conn, request);
94              // Make sure the request body is fully consumed
95              request.getBodyBytes();
96              conn.writeResponse(response);
97              return true;
98          }
99      }
100 
101     //TODO add more auth schemes
102     private SimpleResponse performBasicHandshake(
103             final SimpleHttpServerConnection conn,
104             final SimpleRequest request) throws IOException 
105     { 
106         SimpleResponse response = new SimpleResponse();
107         response.setStatusLine(
108                 request.getRequestLine().getHttpVersion(),
109                 HttpStatus.SC_UNAUTHORIZED);
110         if (!request.getRequestLine().getMethod().equalsIgnoreCase("HEAD")) {
111             response.setBodyString("unauthorized");
112         }
113         response.addHeader(new Header("WWW-Authenticate", "basic realm=\"" + this.realm + "\""));
114         if (this.keepalive) {
115             response.addHeader(new Header("Connection", "keep-alive"));
116             conn.setKeepAlive(true);
117         } else {
118             response.addHeader(new Header("Connection", "close"));
119             conn.setKeepAlive(false);
120         }
121         return response;
122     }
123 
124     /***
125      * Checks if the credentials provided by the client match the required
126      * credentials
127      * 
128      * @return true if the client is authorized, false if not.
129      * @param clientAuth
130      */
131     private boolean checkAuthorization(final Header clientAuth) {
132         String expectedAuthString = BasicScheme.authenticate(
133             (UsernamePasswordCredentials)credentials,
134             "ISO-8859-1");
135         return expectedAuthString.equals(clientAuth.getValue());
136     }
137 
138 }