Source Code Cross Referenced for BasicAuthHandler.java in  » Web-Server » Brazil » sunlabs » brazil » handler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Brazil » sunlabs.brazil.handler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * BasicAuthHandler.java
003:         *
004:         * Brazil project web application Framework,
005:         * export version: 1.1 
006:         * Copyright (c) 1998-2001 Sun Microsystems, Inc.
007:         *
008:         * Sun Public License Notice
009:         *
010:         * The contents of this file are subject to the Sun Public License Version 
011:         * 1.0 (the "License"). You may not use this file except in compliance with 
012:         * the License. A copy of the License is included as the file "license.terms",
013:         * and also available at http://www.sun.com/
014:         * 
015:         * The Original Code is from:
016:         *    Brazil project web application Framework release 1.1.
017:         * The Initial Developer of the Original Code is: suhler.
018:         * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
019:         * All Rights Reserved.
020:         * 
021:         * Contributor(s): cstevens, suhler.
022:         *
023:         * Version:  1.27
024:         * Created by suhler on 98/09/14
025:         * Last modified by suhler on 01/01/12 08:25:13
026:         */
027:
028:        package sunlabs.brazil.handler;
029:
030:        import sunlabs.brazil.server.Handler;
031:        import sunlabs.brazil.server.Request;
032:        import sunlabs.brazil.server.Server;
033:        import sunlabs.brazil.session.SessionManager;
034:        import sunlabs.brazil.util.Format;
035:
036:        import java.io.InputStream;
037:        import java.util.Properties;
038:        import java.util.Hashtable;
039:        import java.util.Enumeration;
040:        import java.util.StringTokenizer;
041:        import java.io.IOException;
042:
043:        /**
044:         * The <code>BasicAuthHandler</code> obtains a Session ID by performing
045:         * "basic" authentication, using either the "Authorization" or the
046:         * "Proxy-Authorization" headers.  This handler prevents
047:         * subsequent downstream handlers from being accessed unless the proper
048:         * authentication was seen in the request.  The Session ID obtained by this
049:         * handler is meant to be used by those downsteams handlers to access
050:         * whatever session-dependent information they need.
051:         * <p>
052:         * If the request does not contain the authentication headers or the
053:         * authentication information is not valid, this handler sends an HTTP
054:         * error message along with the "WWW-Authenticate" or "Proxy-Authenticate"
055:         * header, as appropriate.  See
056:         * <code><a href=#config.code>code</a></code>,
057:         * <code><a href=#config.authorization>authorization</a></code>,
058:         * <code><a href=#config.authenticate>authenticate</a></code>
059:         * <p>
060:         * If the request does contain valid authentication information, the
061:         * Session ID associated with the authentication information is inserted
062:         * into the request properties, for use by downstream handlers.  After
063:         * inserting the Session ID, this handler returns <code>false</code> to
064:         * allow the downstream handlers to run.  
065:         * <p>
066:         * The set of valid Session IDs is contained either in (1) a static file or
067:         * in (2) a globally accessible table managed by the <code>SessionManager</code>.
068:         * The second case allows the list of Session IDs to be dynamically
069:         * configurable and shareable amongst two or more authentication handlers.
070:         * For instance, the web developer could set up one handler to dynamically
071:         * populate the shared table with Session IDs based on submitted HTML forms,
072:         * and then use the <code>BasicAuthHandler</code> to ensure that all other
073:         * requests have a valid Session ID based on the shared table.  See
074:         * <code><a href=#config.code>mapFile</a></code>,
075:         * <code><a href=#config.authorization>session</a></code>,
076:         * <code><a href=#config.authenticate>ident</a></code>
077:         * <p>
078:         * The format of the static file described in case (1) above is a
079:         * Java properties file where keys are the Base64 encoded strings obtained
080:         * from the Authentication header and the values are the associated Session
081:         * IDs.  Base64 strings can contain the '=' character, but the keys in a
082:         * Java properties file cannot contain an '=' character, so all '=' characters
083:         * in the Base64 strings must be converted to '!' in the properties file,
084:         * as shown in the following sample properties file:
085:         * <pre>
086:         * bXIuIGhhdGU6a2ZqYw!! = radion
087:         * Zm9vOmJhcg!! = foo
088:         * </pre>
089:         * The format of the dynamic table described in case (2) above is a
090:         * <code>Hashtable</code> where the keys are the Base64 encoded strings
091:         * obtained from the Authentication header and the values are the associated
092:         * Session IDs.  This <code>Hashtable</code> is accessed via the
093:         * <code>SessionManager.getSession</code> method, with the <code>session</code>
094:         * argument of <code>null</code> and the <code>ident</code> argument
095:         * specified by a configuration parameter.  
096:         * <hr>
097:         * There are several different types of authentication possible.  All
098:         * authentication handlers should follow these basic principles: <ul>
099:         * <li> The authentication handler examines some aspect of the request
100:         *	to decide if the appropriate authentication is present.
101:         * <li> If the request is acceptable, the authentication handler should
102:         *	insert the extracted Session ID into a request property
103:         *	and then return <code>false</code>, to allow subsequent handlers
104:         *	to run and perhaps use the Session ID.
105:         * <li> If the request is not acceptable, the authentication handler can
106:         *	return an error message or do some other thing to try to obtain a
107:         *	valid authentication.
108:         * <li> Handlers wishing to be protected by authentication should not
109:         *	subclass an authentication handler.  Instead, such handler should
110:         *	be written to assume that authentication has already been performed
111:         *	and then just examine the Session ID present.  
112:         *	The web developer is then responsible for choosing which one (of
113:         *	possibly many) forms of authentication to use and installing those
114:         *	authentication handlers before the "sensitive" handler.
115:         * <li> Handlers that are protected by an authentication handler can
116:         *	use the Session ID stored in the request properties regardless of
117:         *	the specifics of the authentication handler.
118:         * </ul>
119:         * <pre>
120:         * handlers=auth history file
121:         *
122:         * auth.class=BasicAuthHandler
123:         * auth.session=account
124:         * auth.message=Go away, you're not allowed here!
125:         *
126:         * history.class=HistoryHandler
127:         * history.session=account
128:         *
129:         * file.class=FileHandler
130:         * file.root=htdocs
131:         * </pre>
132:         * In the sample pseudo-configuation file specified above, the
133:         * <code>BasicAuthHandler</code> is first invoked to see if the HTTP "basic"
134:         * authentication header is present in the request.  If it isn't, a nasty
135:         * message is sent back.  If the "basic" authentication header is present
136:         * and corresponds to a user that the <code>BasicAuthHandler</code> knows
137:         * about, the Session ID associated with that user is stored in the specified
138:         * property named "account".
139:         * <p>
140:         * Subsequently, the <code>HistoryHandler</code> examines its specified
141:         * property (also "account") for the Session ID and uses that to keep
142:         * track of which session is issuing the HTTP request.
143:         * <p>
144:         * Each handler that needs a Session ID should have a
145:         * configuration parameter that allows the web developer to specify the
146:         * name of the request property that holds the Session ID.
147:         * Multiple handlers can all use the same request property as each other,
148:         * all protected by the same authentication handler.
149:         * <hr>
150:         * This handler uses the following configuration properties: <dl class=props>
151:         *
152:         * <dt> <code>prefix</code>
153:         * <dd> This handler will attempt to authenticate URLs beginning with
154:         *	this string only.  The default value is "/".
155:         *
156:         * <a name=config.code> </a>
157:         * <dt> <code>code</code>
158:         * <dd> The type of authentication to perform.  The default value is 401.
159:         *	<p>
160:         *	The value 401 corresponds to standard "basic" authentication.
161:         *	The "Authorization" request header is supposed to contain the
162:         *	authentication string.  If the request was not authenticated, the
163:         *	"WWW-Authenticate" header is sent in the HTTP error response
164:         *	to cause the browser to prompt the client to authenticate.
165:         *	<p>
166:         *	The value 407 corresponds to "basic" proxy/firewall authentication.
167:         *	The "Proxy-Authorization" request header is supposed to contain the
168:         *	authentication string.  If the request was not authenticated, the
169:         *	"Proxy-Authenticate" header is sent in the HTTP error response
170:         *	to cause the browser to prompt the client to authenticate.
171:         *	<p>
172:         *	Any other value may also be specified.  Whatever the value, it will
173:         *	be returned as the HTTP result code of the error message.
174:         *
175:         * <a name=config.authorization> </a>
176:         * <dt> <code>authorization</code>
177:         * <dd> If specified, this is the request header that will contain the
178:         *	"basic" authentication string, instead of the "Authorization"
179:         *	or "Proxy-Authorization" header implied by <code>code</code>.
180:         *
181:         * <a name=config.authenticate> </a>
182:         * <dt> <code>authenticate</code>
183:         * <dd> If specified, this is the response header that will be sent in the
184:         *	HTTP error response if the user is not authenticated.
185:         *	<p>
186:         *	If this string is "", then this handler will
187:         *	authenticate the request if the authorization header is present,
188:         *	but <b>will not</b> send an HTTP error message if the request could
189:         *	not be authenticated.  This is useful if the web developer wants to
190:         *	do something more complex (such as invoking an arbitrary set of
191:         *	handlers) instead of just sending a simple error message if the
192:         *	request was not authenticated.  In this case, the web developer can
193:         *	determine that the request was not authenticated because <b>no</b>
194:         *	Session ID will be present in the request properties.
195:         *
196:         * <dt> <code>realm</code>
197:         * <dd> The "realm" of the HTTP authentication error message.  This is a
198:         *	string that the browser is supposed to present to the client when
199:         *	asking the client the authenticate.  It provides a human-friendly
200:         *	name describing who wants the authentication.
201:         *
202:         * <dt> <code>message</code>
203:         * <dd> The body of the HTTP authentication error message.  This will be
204:         *	displayed by the browser if the client chooses not to authenticate.
205:         *	The default value is "".  Patterns of the form <i>${xxx}</i> are
206:         *	replaced with the value of the <i>xxx</i>
207:         *	entry of <code>request.props</code>.
208:         *
209:         * <dt> <code>mapFile</code>
210:         * <dd> If specified, this is the Session ID file.  This is expected to be
211:         *	a java properties file, whose keys are the authentication tokens,
212:         *	and whose values are the Session IDs that are inserted into the
213:         *	request properties.
214:         *	<p>
215:         *	The keys in the file are basic authentication (base64) tokens with
216:         *	any trailing <code>"="</code> characters changed to <code>"!"</code>.
217:         *
218:         * <dt> <code>session</code>
219:         * <dd> The name of the request property that the Session ID will be stored
220:         *	in, to be passed to downstream handlers.  The default value is
221:         *	"SessionID". 
222:         *
223:         * <dt>	<code>ident</code>
224:         * <dd> The <code>ident</code> argument to {@link SessionManager#getSession}
225:         *	to get the table of valid sessions.  The default value is
226:         *	"authorized".
227:         * </dl>
228:         *
229:         * @author	Stephen Uhler (stephen.uhler@sun.com)
230:         * @author	Colin Stevens (colin.stevens@sun.com)
231:         * @version	1.27, 01/01/12
232:         */
233:        public class BasicAuthHandler implements  Handler {
234:            private static final String PREFIX = "prefix";
235:            private static final String CODE = "code";
236:            private static final String AUTHORIZATION = "authorization";
237:            private static final String AUTHENTICATE = "authenticate";
238:            private static final String REALM = "realm";
239:            private static final String MESSAGE = "message";
240:            private static final String MAP_FILE = "mapFile";
241:            private static final String SESSION = "session";
242:            private static final String IDENT = "ident";
243:
244:            public String prefix = "/";
245:            public int code = 401;
246:            public String authorization = "Authorization";
247:            public String authenticate = "WWW-Authenticate";
248:            public String realm = "realm";
249:            public String message = "Invalid credentials supplied";
250:            public String mapFile = null;
251:            public String session = "SessionID";
252:            public String ident = "authorized";
253:
254:            String propsPrefix;
255:
256:            public Properties map; // The authorization mapping table
257:
258:            /**
259:             * Initializes this handler.  It is an error if the <code>mapFile</code>
260:             * parameter is specified but that file cannot be loaded.
261:             *
262:             * @param	server
263:             *		The HTTP server that created this handler.
264:             *
265:             * @param	prefix
266:             *		A prefix to prepend to all of the keys that this
267:             *		handler uses to extract configuration information.
268:             *
269:             * @return	<code>true</code> if this <code>Handler</code> initialized
270:             *		successfully, <code>false</code> otherwise.
271:             */
272:            public boolean init(Server server, String propsPrefix) {
273:                Properties props = server.props;
274:
275:                this .prefix = props.getProperty(propsPrefix + PREFIX,
276:                        this .prefix);
277:                this .propsPrefix = propsPrefix;
278:                try {
279:                    String str = props.getProperty(propsPrefix + CODE);
280:                    code = Integer.decode(str).intValue();
281:                } catch (Exception e) {
282:                }
283:
284:                if (code == 407) {
285:                    authorization = "Proxy-Authorization";
286:                    authenticate = "Proxy-Authenticate";
287:                }
288:                authorization = props.getProperty(propsPrefix + AUTHORIZATION,
289:                        authorization);
290:                authenticate = props.getProperty(propsPrefix + AUTHENTICATE,
291:                        authenticate);
292:                realm = props.getProperty(propsPrefix + REALM, realm);
293:                message = props.getProperty(propsPrefix + MESSAGE, message);
294:                mapFile = props.getProperty(propsPrefix + MAP_FILE, mapFile);
295:                session = props.getProperty(propsPrefix + SESSION, session);
296:                ident = props.getProperty(propsPrefix + IDENT, ident);
297:
298:                try {
299:                    if (message.startsWith("@")) {
300:                        message = ResourceHandler.getResourceString(
301:                                server.props, propsPrefix, message);
302:                    }
303:                } catch (IOException e) {
304:                    server.log(Server.LOG_ERROR, propsPrefix,
305:                            "Can't get \"denied\" message");
306:                }
307:
308:                if (mapFile != null)
309:                    try {
310:                        server.log(Server.LOG_DIAGNOSTIC, propsPrefix,
311:                                "Loading credentials file " + mapFile);
312:                        InputStream in = ResourceHandler.getResourceStream(
313:                                server.props, propsPrefix, mapFile);
314:                        Properties p = new Properties();
315:                        p.load(in);
316:                        in.close();
317:
318:                        map = new Properties();
319:                        Enumeration keys = p.keys();
320:                        while (keys.hasMoreElements()) {
321:                            String key = (String) keys.nextElement();
322:                            String value = (String) p.get(key);
323:                            map.put(key.replace('!', '='), value);
324:                        }
325:                    } catch (Exception e) {
326:                        server.log(Server.LOG_DIAGNOSTIC, propsPrefix,
327:                                "Credentials file (" + mapFile
328:                                        + ") not available: " + e);
329:                    }
330:                mapFile = null;
331:                return true;
332:            }
333:
334:            /**
335:             * Looks up the credentials for this request, and insert them into the
336:             * request stream.  If no credentials are found, prompt the user for them.
337:             */
338:
339:            public boolean respond(Request request) throws IOException {
340:                if (request.url.startsWith(prefix) == false) {
341:                    return false;
342:                }
343:
344:                String auth = request.headers.get(authorization);
345:                if (auth == null) {
346:                    return complain(request, "Missing http header: "
347:                            + authorization);
348:                }
349:
350:                try {
351:                    /*
352:                     * Strip off "basic" at beginning of value.
353:                     */
354:
355:                    StringTokenizer st = new StringTokenizer(auth);
356:                    if ("basic".equalsIgnoreCase(st.nextToken()) == false) {
357:                        return complain(request, "Non-basic realm: " + auth);
358:                    }
359:
360:                    auth = st.nextToken();
361:
362:                    String id;
363:                    if (map == null) {
364:                        Hashtable h = (Hashtable) SessionManager.getSession(
365:                                null, ident, Hashtable.class);
366:                        id = (String) h.get(auth);
367:                    } else {
368:                        id = map.getProperty(auth);
369:                    }
370:                    if (id == null) {
371:                        return complain(request, "no id matching: " + auth);
372:                    }
373:
374:                    /*
375:                     * Found registered user, so add user to request properties.
376:                     */
377:                    request.props.put(session, id);
378:                    request.props.put("gotCookie", "true");
379:                    request.log(Server.LOG_DIAGNOSTIC, propsPrefix, "Setting "
380:                            + session + " to: " + id);
381:                    return false;
382:                } catch (Exception e) {
383:                    /* Malformed authorization. */
384:                    return complain(request, e.toString());
385:                }
386:            }
387:
388:            /**
389:             * Authentication failed.
390:             * Send the appropriate authentication required header as a response.
391:             * @param request	The request to respond to
392:             * @param reason	The reason for failure (for diagnostics)
393:             * @returns		True
394:             */
395:
396:            public boolean complain(Request request, String reason)
397:                    throws IOException {
398:                if (authenticate.length() == 0) {
399:                    request.log(Server.LOG_DIAGNOSTIC, propsPrefix,
400:                            "no authenticate?");
401:                    return false;
402:                }
403:                request
404:                        .addHeader(authenticate, "basic realm=\"" + realm
405:                                + "\"");
406:                request.sendResponse(Format.subst(request.props, message),
407:                        "text/html", code);
408:                request.log(Server.LOG_DIAGNOSTIC, propsPrefix, reason);
409:                return true;
410:            }
411:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.