Source Code Cross Referenced for JDBCEncryptionRealm.java in  » J2EE » Jaffa » org » jaffa » tomcat » realm » 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 » J2EE » Jaffa » org.jaffa.tomcat.realm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ====================================================================
0003:         * JAFFA - Java Application Framework For All
0004:         *
0005:         * Copyright (C) 2002 JAFFA Development Group
0006:         *
0007:         *     This library is free software; you can redistribute it and/or
0008:         *     modify it under the terms of the GNU Lesser General Public
0009:         *     License as published by the Free Software Foundation; either
0010:         *     version 2.1 of the License, or (at your option) any later version.
0011:         *
0012:         *     This library is distributed in the hope that it will be useful,
0013:         *     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015:         *     Lesser General Public License for more details.
0016:         *
0017:         *     You should have received a copy of the GNU Lesser General Public
0018:         *     License along with this library; if not, write to the Free Software
0019:         *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0020:         *
0021:         * Redistribution and use of this software and associated documentation ("Software"),
0022:         * with or without modification, are permitted provided that the following conditions are met:
0023:         * 1.	Redistributions of source code must retain copyright statements and notices.
0024:         *         Redistributions must also contain a copy of this document.
0025:         * 2.	Redistributions in binary form must reproduce the above copyright notice,
0026:         * 	this list of conditions and the following disclaimer in the documentation
0027:         * 	and/or other materials provided with the distribution.
0028:         * 3.	The name "JAFFA" must not be used to endorse or promote products derived from
0029:         * 	this Software without prior written permission. For written permission,
0030:         * 	please contact mail to: jaffagroup@yahoo.com.
0031:         * 4.	Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
0032:         * 	appear in their names without prior written permission.
0033:         * 5.	Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
0034:         *
0035:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0036:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0037:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0038:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0039:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0040:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0041:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0042:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0043:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0044:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0045:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0046:         * SUCH DAMAGE.
0047:         * ====================================================================
0048:         * The Apache Software License, Version 1.1
0049:         *
0050:         * Copyright (c) 1999 The Apache Software Foundation.  All rights
0051:         * reserved.
0052:         *
0053:         * Redistribution and use in source and binary forms, with or without
0054:         * modification, are permitted provided that the following conditions
0055:         * are met:
0056:         *
0057:         * 1. Redistributions of source code must retain the above copyright
0058:         *    notice, this list of conditions and the following disclaimer.
0059:         *
0060:         * 2. Redistributions in binary form must reproduce the above copyright
0061:         *    notice, this list of conditions and the following disclaimer in
0062:         *    the documentation and/or other materials provided with the
0063:         *    distribution.
0064:         *
0065:         * 3. The end-user documentation included with the redistribution, if
0066:         *    any, must include the following acknowlegement:
0067:         *       "This product includes software developed by the
0068:         *        Apache Software Foundation (http://www.apache.org/)."
0069:         *    Alternately, this acknowlegement may appear in the software itself,
0070:         *    if and wherever such third-party acknowlegements normally appear.
0071:         *
0072:         * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0073:         *    Foundation" must not be used to endorse or promote products derived
0074:         *    from this software without prior written permission. For written
0075:         *    permission, please contact apache@apache.org.
0076:         *
0077:         * 5. Products derived from this software may not be called "Apache"
0078:         *    nor may "Apache" appear in their names without prior written
0079:         *    permission of the Apache Group.
0080:         *
0081:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0082:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0083:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0084:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0085:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0086:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0087:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0088:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0089:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0090:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0091:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0092:         * SUCH DAMAGE.
0093:         * ====================================================================
0094:         *
0095:         * This software consists of voluntary contributions made by many
0096:         * individuals on behalf of the Apache Software Foundation.  For more
0097:         * information on the Apache Software Foundation, please see
0098:         * <http://www.apache.org/>.
0099:         *
0100:         * [Additional notices, if required by prior licensing conditions]
0101:         *
0102:         */
0103:        package org.jaffa.tomcat.realm;
0104:
0105:        import java.io.File;
0106:        import java.lang.reflect.InvocationTargetException;
0107:        import java.lang.reflect.Method;
0108:        import java.lang.reflect.Modifier;
0109:        import java.security.GeneralSecurityException;
0110:        import java.security.MessageDigest;
0111:        import java.security.Principal;
0112:        import java.sql.Connection;
0113:        import java.sql.Driver;
0114:        import java.sql.PreparedStatement;
0115:        import java.sql.ResultSet;
0116:        import java.sql.SQLException;
0117:        import java.util.ArrayList;
0118:        import java.util.Properties;
0119:        import javax.naming.Context;
0120:        import javax.naming.InitialContext;
0121:        import javax.naming.NamingException;
0122:        import javax.sql.DataSource;
0123:        import org.apache.catalina.Container;
0124:        import org.apache.catalina.Lifecycle;
0125:        import org.apache.catalina.LifecycleEvent;
0126:        import org.apache.catalina.LifecycleException;
0127:        import org.apache.catalina.LifecycleListener;
0128:        import org.apache.catalina.Logger;
0129:        import org.apache.catalina.Realm;
0130:        import org.apache.catalina.Server;
0131:        import org.apache.catalina.ServerFactory;
0132:        import org.apache.catalina.core.StandardServer;
0133:        import org.apache.catalina.realm.Constants;
0134:        import org.apache.catalina.realm.GenericPrincipal;
0135:        import org.apache.catalina.realm.RealmBase;
0136:        import org.apache.catalina.util.Base64;
0137:        import org.apache.catalina.util.HexUtils;
0138:        import org.apache.catalina.util.LifecycleSupport;
0139:        import org.apache.catalina.util.StringManager;
0140:
0141:        /**
0142:         * This Realm included the functionality of both the standard tomcat
0143:         * {@link org.apache.catalina.realm.JDBCRealm JDBCRealm}
0144:         * and the {@link org.apache.catalina.realm.DataSourceRealm DataSourceRealm},
0145:         * in one class. It also included the ability to perform custom
0146:         * password encryption using 3rd party classes (if your encryption scheme is not
0147:         * supported by the default MessageDigest class in the JCE libraries).
0148:         * <p>
0149:         * This new version works with <b>Tomcat 4.1</b> and higher, the previous version that doesn't
0150:         * have the DataSource code in it, works with ther earlier Tomcat 4.0 release
0151:         * <p>
0152:         * The code based for this classes was taken from the Tomcat 4.1.26 release
0153:         * <p>
0154:         * The two properties used for encryption are : encryptionClass and encryptionMethod.
0155:         * <p>
0156:         * With these set, the realm introspects for the named class for the names method. It
0157:         * is expected that the method has one of the following signatures
0158:         * <pre>
0159:         *      <code>public static String methodName(String password)</code>
0160:         * </pre>
0161:         * or
0162:         * <pre>
0163:         *      <code>public static String methodName(String password, String username)</code>
0164:         * </pre>
0165:         * The method should return a string, that should match the value retrieved from the
0166:         * database. This allow one-way encryption algorithms to be used. No decryption facility
0167:         * needs to be provided.
0168:         * <p>
0169:         * In addition to the original JDBCRealm/DataSource this realm
0170:         * <ol>
0171:         *  <li>does not throw a NullPointerException if the database password is null
0172:         *  <li>considers a user validated if the database and entered password are both null
0173:         *  <li>provided one-way password encryption prior to comparing them
0174:         *  <li>allows extention to the query to get the user's credentials
0175:         *  <li>allows a custom query to be suppplied for getting the user's roles
0176:         *  <li>Message levels for 'debug' parameter are 0 ->None, 2+ ->Errors, 5+ ->Warnings, 10+ ->Debug
0177:         * </ol>
0178:         * New in Version 1.3
0179:         * <ul>
0180:         * <li>Adds support for DataSources. If the 'dataSourceName' is passed it overrides
0181:         * the use of a regular connection, therefore it ignores the values for <code>connectionName,
0182:         * connectionPassword, connectionURL</code> and <code>driverName</code>
0183:         * <li>Uses its own LocalStrings for messages, incase you want to implement a diffenent language
0184:         * </ul>
0185:         * For more documentation see the <a href="http://jaffa.sourceforge.net/documentation/security/web/#realm">Jaffa Web Site</a>
0186:         * <p>
0187:         * @author Paul Extance
0188:         * @version 1.3
0189:         */
0190:
0191:        public class JDBCEncryptionRealm extends RealmBase {
0192:
0193:            // ----------------------------------------------------- Instance Variables
0194:
0195:            /**
0196:             * The name of the JNDI JDBC DataSource
0197:             */
0198:            protected String dataSourceName = null;
0199:
0200:            /**
0201:             * The connection username to use when trying to connect to the database.
0202:             */
0203:            protected String connectionName = null;
0204:
0205:            /**
0206:             * The connection URL to use when trying to connect to the database.
0207:             */
0208:            protected String connectionPassword = null;
0209:
0210:            /**
0211:             * The connection URL to use when trying to connect to the database.
0212:             */
0213:            protected String connectionURL = null;
0214:
0215:            /**
0216:             * The connection to the database.
0217:             */
0218:            protected Connection dbConnection = null;
0219:
0220:            /**
0221:             * Instance of the JDBC Driver class we use as a connection factory.
0222:             */
0223:            protected Driver driver = null;
0224:
0225:            /**
0226:             * The JDBC driver to use.
0227:             */
0228:            protected String driverName = null;
0229:
0230:            /**
0231:             * Descriptive information about this Realm implementation.
0232:             */
0233:            protected static final String info = "org.jaffa.tomcat.realm.JDBCEncryptionRealm/1.2";
0234:
0235:            /**
0236:             * Descriptive information about this Realm implementation.
0237:             */
0238:            protected static final String name = "JDBCEncryptionRealm";
0239:
0240:            /**
0241:             * The PreparedStatement to use for authenticating users.
0242:             */
0243:            protected PreparedStatement preparedCredentials = null;
0244:
0245:            /**
0246:             * The generated string for the roles PreparedStatement
0247:             */
0248:            private StringBuffer preparedRolesSB = null;
0249:
0250:            /**
0251:             * The PreparedStatement to use for identifying the roles for
0252:             * a specified user.
0253:             */
0254:            protected PreparedStatement preparedRoles = null;
0255:
0256:            /**
0257:             * The generated string for the credentials PreparedStatement
0258:             */
0259:            private StringBuffer preparedCredentialsSB = null;
0260:
0261:            /**
0262:             * The column in the user role table that names a role
0263:             */
0264:            protected String roleNameCol = null;
0265:
0266:            /**
0267:             * The string manager for this package.
0268:             */
0269:            protected static final StringManager sm = StringManager
0270:                    .getManager("org.jaffa.tomcat.realm");
0271:
0272:            /**
0273:             * The column in the user table that holds the user's credintials
0274:             */
0275:            protected String userCredCol = null;
0276:
0277:            /**
0278:             * The column in the user table that holds the user's name
0279:             */
0280:            protected String userNameCol = null;
0281:
0282:            /**
0283:             * The table that holds the relation between user's and roles
0284:             */
0285:            protected String userRoleTable = null;
0286:
0287:            /**
0288:             * The table that holds user data.
0289:             */
0290:            protected String userTable = null;
0291:
0292:            /** Holds value of property encryptionClass. */
0293:            private String encryptionClass;
0294:
0295:            /** Holds value of property encryptionMethod. */
0296:            private String encryptionMethod;
0297:
0298:            /** Holds value of the real encryption method to use. */
0299:            private Method eMethod;
0300:
0301:            /** Holds value of property roleSelect. */
0302:            private String roleSelect;
0303:
0304:            /** Holds value of property userClause. */
0305:            private String userClause;
0306:
0307:            // ------------------------------------------------------------- Properties
0308:
0309:            /** Return the name of the JNDI JDBC DataSource.
0310:             * @since 1.3
0311:             * @return Name of the JNDI JDBC DataSource
0312:             */
0313:            public String getDataSourceName() {
0314:                return dataSourceName;
0315:            }
0316:
0317:            /**
0318:             * Set the name of the JNDI JDBC DataSource.
0319:             *
0320:             * @param dataSourceName the name of the JNDI JDBC DataSource
0321:             * @since 1.3
0322:             */
0323:            public void setDataSourceName(String dataSourceName) {
0324:                this .dataSourceName = dataSourceName;
0325:            }
0326:
0327:            /** Return the username to use to connect to the database.
0328:             * @return Username to use to connect to the database
0329:             */
0330:            public String getConnectionName() {
0331:                return connectionName;
0332:            }
0333:
0334:            /**
0335:             * Set the username to use to connect to the database.
0336:             *
0337:             * @param connectionName Username
0338:             */
0339:            public void setConnectionName(String connectionName) {
0340:                this .connectionName = connectionName;
0341:            }
0342:
0343:            /** Return the password to use to connect to the database.
0344:             * @return Password to use to connect to the database
0345:             */
0346:            public String getConnectionPassword() {
0347:                return connectionPassword;
0348:            }
0349:
0350:            /**
0351:             * Set the password to use to connect to the database.
0352:             *
0353:             * @param connectionPassword User password
0354:             */
0355:            public void setConnectionPassword(String connectionPassword) {
0356:                this .connectionPassword = connectionPassword;
0357:            }
0358:
0359:            /** Return the URL to use to connect to the database.
0360:             * @return URL to use to connect to the database
0361:             */
0362:            public String getConnectionURL() {
0363:                return connectionURL;
0364:            }
0365:
0366:            /**
0367:             * Set the URL to use to connect to the database.
0368:             *
0369:             * @param connectionURL The new connection URL
0370:             */
0371:            public void setConnectionURL(String connectionURL) {
0372:                this .connectionURL = connectionURL;
0373:            }
0374:
0375:            /** Return the JDBC driver that will be used.
0376:             * @return JDBC driver that will be used
0377:             */
0378:            public String getDriverName() {
0379:                return driverName;
0380:            }
0381:
0382:            /**
0383:             * Set the JDBC driver that will be used.
0384:             *
0385:             * @param driverName The driver name
0386:             */
0387:            public void setDriverName(String driverName) {
0388:                this .driverName = driverName;
0389:            }
0390:
0391:            /** Return the column in the user role table that names a role.
0392:             * @return Column in the user role table that names a role
0393:             */
0394:            public String getRoleNameCol() {
0395:                return roleNameCol;
0396:            }
0397:
0398:            /**
0399:             * Set the column in the user role table that names a role.
0400:             *
0401:             * @param roleNameCol The column name
0402:             */
0403:            public void setRoleNameCol(String roleNameCol) {
0404:                this .roleNameCol = roleNameCol;
0405:            }
0406:
0407:            /** Return the column in the user table that holds the user's credentials.
0408:             * @return Column in the user table that holds the user's credentials
0409:             */
0410:            public String getUserCredCol() {
0411:                return userCredCol;
0412:            }
0413:
0414:            /**
0415:             * Set the column in the user table that holds the user's credentials.
0416:             *
0417:             * @param userCredCol The column name
0418:             */
0419:            public void setUserCredCol(String userCredCol) {
0420:                this .userCredCol = userCredCol;
0421:            }
0422:
0423:            /** Return the column in the user table that holds the user's name.
0424:             * @return Column in the user table that holds the user's name
0425:             */
0426:            public String getUserNameCol() {
0427:                return userNameCol;
0428:            }
0429:
0430:            /**
0431:             * Set the column in the user table that holds the user's name.
0432:             *
0433:             * @param userNameCol The column name
0434:             */
0435:            public void setUserNameCol(String userNameCol) {
0436:                this .userNameCol = userNameCol;
0437:            }
0438:
0439:            /** Return the table that holds the relation between user's and roles.
0440:             * @return Table that holds the relation between user's and roles
0441:             */
0442:            public String getUserRoleTable() {
0443:                return userRoleTable;
0444:            }
0445:
0446:            /**
0447:             * Set the table that holds the relation between user's and roles.
0448:             *
0449:             * @param userRoleTable The table name
0450:             */
0451:            public void setUserRoleTable(String userRoleTable) {
0452:                this .userRoleTable = userRoleTable;
0453:            }
0454:
0455:            /** Return the table that holds user data.
0456:             * @return Table that holds user data
0457:             */
0458:            public String getUserTable() {
0459:                return userTable;
0460:            }
0461:
0462:            /**
0463:             * Set the table that holds user data.
0464:             *
0465:             * @param userTable The table name
0466:             */
0467:            public void setUserTable(String userTable) {
0468:                this .userTable = userTable;
0469:            }
0470:
0471:            /** Setter for property encryptionClass.
0472:             * @param encryptionClass New value of property encryptionClass.
0473:             */
0474:            public void setEncryptionClass(String encryptionClass) {
0475:                this .encryptionClass = encryptionClass;
0476:            }
0477:
0478:            /** Return the class used for encryption
0479:             * @return Class used for encryption
0480:             */
0481:            public String getEncryptionClass() {
0482:                return encryptionClass;
0483:            }
0484:
0485:            /** Setter for property encryptionMethod.
0486:             * @param encryptionMethod New value of property encryptionMethod.
0487:             */
0488:            public void setEncryptionMethod(String encryptionMethod) {
0489:                this .encryptionMethod = encryptionMethod;
0490:            }
0491:
0492:            /** Return the method used for encryption
0493:             * @return Method used for encryption
0494:             */
0495:            public String getEncryptionMethod() {
0496:                return encryptionMethod;
0497:            }
0498:
0499:            /** Setter for property roleSelect. This, if set is used as an override
0500:             * for creating the complete prepared statement for retriving the list of roles
0501:             * from the database.
0502:             * @param roleSelect New value of property roleSelect.
0503:             */
0504:            public void setRoleSelect(String roleSelect) {
0505:                this .roleSelect = roleSelect;
0506:            }
0507:
0508:            /** Return the alternative select statement for reading the roles
0509:             * @return Alternative select statement for reading the roles
0510:             */
0511:            public String getRoleSelect() {
0512:                return roleSelect;
0513:            }
0514:
0515:            /** Getter for property userClause.
0516:             * @return Value of property userClause.
0517:             */
0518:            public String getUserClause() {
0519:                return this .userClause;
0520:            }
0521:
0522:            /** Setter for property userClause.
0523:             * @param userClause New value of property userClause.
0524:             */
0525:            public void setUserClause(String userClause) {
0526:                this .userClause = userClause;
0527:            }
0528:
0529:            // --------------------------------------------------------- Public Methods
0530:
0531:            /**
0532:             * Return the Principal associated with the specified username and
0533:             * credentials, if there is one; otherwise return <code>null</code>.
0534:             *
0535:             * If there are any errors with the JDBC connection, executing
0536:             * the query or anything we return null (don't authenticate). This
0537:             * event is also logged, and the connection will be closed so that
0538:             * a subsequent request will automatically re-open it.
0539:             *
0540:             * @param username Username of the Principal to look up
0541:             * @param credentials Password or other credentials to use in
0542:             * authenticating this username
0543:             * @return Authenticated principle object, with role access defined
0544:             */
0545:            public Principal authenticate(String username, String credentials) {
0546:
0547:                Connection dbConnection = null;
0548:
0549:                try {
0550:
0551:                    // Ensure that we have an open database connection
0552:                    dbConnection = open();
0553:                    if (dbConnection == null) {
0554:                        // If the db connection open fails, return "not authenticated"
0555:                        return null;
0556:                    }
0557:
0558:                    // Acquire a Principal object for this user
0559:                    Principal principal = null;
0560:                    if (dataSourceName == null)
0561:                        // this is syncronized (for JDBCRealm style)
0562:                        principal = authenticateSync(dbConnection, username,
0563:                                credentials);
0564:                    else
0565:                        // this is NOT syncronized (for DataSourceRealm style)
0566:                        principal = authenticate(dbConnection, username,
0567:                                credentials);
0568:
0569:                    // Return the Principal (if any)
0570:                    return (principal);
0571:
0572:                } catch (SQLException e) {
0573:
0574:                    // Log the problem for posterity
0575:                    log(sm.getString("jdbcEncryptionRealm.error.exception"), e);
0576:
0577:                    // Close the connection so that it gets reopened next time
0578:                    if (dbConnection != null)
0579:                        close(dbConnection);
0580:
0581:                    // Return "not authenticated" for this request
0582:                    return null;
0583:
0584:                } finally {
0585:                    // Release the database connection we just used
0586:                    try {
0587:                        release(dbConnection);
0588:                        dbConnection = null;
0589:                    } catch (SQLException e) {
0590:                        // do nothing
0591:                    }
0592:                }
0593:            }
0594:
0595:            // -------------------------------------------------------- Package Methods
0596:
0597:            // ------------------------------------------------------ Protected Methods
0598:
0599:            /**
0600:             * Return the Principal associated with the specified username and
0601:             * credentials, if there is one; otherwise return <code>null</code>.
0602:             *
0603:             * This is just a syncronization guard, for use in JDBCRealm mode, in
0604:             * DataSourceRealm mode, this is bypasses!
0605:             *
0606:             * @param dbConnection The database connection to be used
0607:             * @param username Username of the Principal to look up
0608:             * @param credentials Password or other credentials to use in
0609:             * authenticating this username
0610:             * @exception SQLException if a database error occurs
0611:             * @return Authenticated principle object, with role access defined
0612:             */
0613:            private synchronized Principal authenticateSync(
0614:                    Connection dbConnection, String username, String credentials)
0615:                    throws SQLException {
0616:                return authenticate(dbConnection, username, credentials);
0617:            }
0618:
0619:            /**
0620:             * Return the Principal associated with the specified username and
0621:             * credentials, if there is one; otherwise return <code>null</code>.
0622:             *
0623:             * @param dbConnection The database connection to be used
0624:             * @param username Username of the Principal to look up
0625:             * @param credentials Password or other credentials to use in
0626:             *  authenticating this username
0627:             *
0628:             * @exception SQLException if a database error occurs
0629:             */
0630:            private Principal authenticate(Connection dbConnection,
0631:                    String username, String credentials) throws SQLException {
0632:
0633:                ResultSet rs = null;
0634:                PreparedStatement stmt = null;
0635:                ArrayList list = null;
0636:
0637:                try {
0638:                    // Look up the user's credentials
0639:                    String dbCredentials = null;
0640:                    stmt = credentials(dbConnection, username);
0641:                    rs = stmt.executeQuery();
0642:                    if (rs.next()) {
0643:                        dbCredentials = rs.getString(1);
0644:                        // Fix Bug, don't trim if returned value is null!
0645:                        if (dbCredentials != null)
0646:                            dbCredentials = dbCredentials.trim();
0647:                        if (rs.next())
0648:                            log(sm.getString(
0649:                                    "jdbcEncryptionRealm.warn.multiple",
0650:                                    username));
0651:                    } else {
0652:                        if (debug >= 2)
0653:                            log(sm.getString(
0654:                                    "jdbcEncryptionRealm.authenticateFailure",
0655:                                    username));
0656:                        return (null);
0657:                    }
0658:                    rs.close();
0659:                    rs = null;
0660:                    stmt.close();
0661:                    stmt = null;
0662:
0663:                    // Validate the user's credentials
0664:                    boolean validated = false;
0665:                    if (dbCredentials == null) {
0666:                        // If no database password and password was entered, then validation passed
0667:                        validated = (credentials == null)
0668:                                || (credentials.trim().length() == 0);
0669:                    } else {
0670:                        // Validate the user's credentials
0671:                        String password = digest(encryptPassword(credentials,
0672:                                username));
0673:                        if (hasMessageDigest()) {
0674:                            // Hex hashes should be compared case-insensitive
0675:                            validated = (password
0676:                                    .equalsIgnoreCase(dbCredentials));
0677:                        } else
0678:                            validated = (password.equals(dbCredentials));
0679:                    }
0680:
0681:                    if (validated) {
0682:                        if (debug >= 2)
0683:                            log(sm.getString(
0684:                                    "jdbcEncryptionRealm.authenticateSuccess",
0685:                                    username));
0686:                    } else {
0687:                        if (debug >= 2)
0688:                            log(sm.getString(
0689:                                    "jdbcEncryptionRealm.authenticateFailure",
0690:                                    username));
0691:                        return (null);
0692:                    }
0693:
0694:                    // Accumulate the user's roles
0695:                    list = new ArrayList();
0696:                    stmt = roles(dbConnection, username);
0697:                    rs = stmt.executeQuery();
0698:                    while (rs.next()) {
0699:                        list.add(rs.getString(1).trim());
0700:                    }
0701:                } catch (GeneralSecurityException e) {
0702:                    // Make sure if there are any errors not to allow authnetication
0703:                    log(e.getMessage());
0704:                    return null;
0705:                } finally {
0706:                    if (rs != null) {
0707:                        rs.close();
0708:                    }
0709:                    if (stmt != null) {
0710:                        stmt.close();
0711:                    }
0712:                }
0713:
0714:                // Create and return a suitable Principal for this user
0715:                return (new GenericPrincipal(this , username, credentials, list));
0716:
0717:            }
0718:
0719:            /** If special encryption is needed, this is applied to the password
0720:             */
0721:            private String encryptPassword(String pass, String user)
0722:                    throws GeneralSecurityException {
0723:                try {
0724:                    if (this .eMethod == null) {
0725:                        if (debug >= 10)
0726:                            log(sm
0727:                                    .getString("jdbcEncryptionRealm.debug.bypass"));
0728:                        return pass;
0729:                    }
0730:                    if (this .eMethod.getParameterTypes().length == 1) {
0731:                        if (debug >= 10)
0732:                            log(sm.getString("jdbcEncryptionRealm.debug.type1"));
0733:                        return (String) this .eMethod.invoke(null,
0734:                                new Object[] { pass });
0735:                    } else if (this .eMethod.getParameterTypes().length == 2) {
0736:                        if (debug >= 10)
0737:                            log(sm.getString("jdbcEncryptionRealm.debug.type2"));
0738:                        return (String) this .eMethod.invoke(null, new Object[] {
0739:                                pass, user });
0740:                    } else {
0741:                        throw new GeneralSecurityException(sm.getString(
0742:                                "jdbcEncryptionRealm.badMethod",
0743:                                encryptionClass));
0744:                    }
0745:                } catch (IllegalAccessException e) {
0746:                    throw new GeneralSecurityException(sm.getString(
0747:                            "jdbcEncryptionRealm.encryption", e.getMessage()));
0748:                } catch (IllegalArgumentException e) {
0749:                    throw new GeneralSecurityException(sm.getString(
0750:                            "jdbcEncryptionRealm.encryption", e.getMessage()));
0751:                } catch (InvocationTargetException e) {
0752:                    throw new GeneralSecurityException(sm.getString(
0753:                            "jdbcEncryptionRealm.encryption", e.getMessage()));
0754:                }
0755:            }
0756:
0757:            /**
0758:             * Close the specified database connection.
0759:             *
0760:             * @param dbConnection The connection to be closed
0761:             */
0762:            protected void close(Connection dbConnection) {
0763:
0764:                // Do nothing if the database connection is already closed
0765:                if (dbConnection == null)
0766:                    return;
0767:
0768:                // Close our prepared statements (if any)
0769:                try {
0770:                    if (preparedCredentials != null)
0771:                        preparedCredentials.close();
0772:                } catch (Throwable f) {
0773:                    ;
0774:                }
0775:                try {
0776:                    if (preparedRoles != null)
0777:                        preparedRoles.close();
0778:                } catch (Throwable f) {
0779:                    ;
0780:                }
0781:
0782:                // Close this database connection, and log any errors
0783:                try {
0784:                    dbConnection.close();
0785:                } catch (SQLException e) {
0786:                    log(sm.getString("jdbcEncryptionRealm.error.close"), e); // Just log it here
0787:                }
0788:
0789:                // Release resources associated with the closed connection
0790:                this .dbConnection = null;
0791:                this .preparedCredentials = null;
0792:                this .preparedRoles = null;
0793:
0794:            }
0795:
0796:            /** Return a PreparedStatement configured to perform the SELECT required
0797:             * to retrieve user credentials for the specified username.
0798:             *
0799:             * @param dbConnection The database connection to be used
0800:             * @param username Username for which credentials should be retrieved
0801:             * @exception SQLException if a database error occurs
0802:             * @return PreparedStatement to read user's password
0803:             */
0804:            protected PreparedStatement credentials(Connection dbConnection,
0805:                    String username) throws SQLException {
0806:
0807:                if (preparedCredentials == null) {
0808:                    /*
0809:                    StringBuffer sb = new StringBuffer("SELECT ");
0810:                    sb.append(userCredCol);
0811:                    sb.append(" FROM ");
0812:                    sb.append(userTable);
0813:                    sb.append(" WHERE ");
0814:                    sb.append(userNameCol);
0815:                    sb.append(" = ?");
0816:                    if(getUserClause()!=null) {
0817:                    sb.append(" AND ");
0818:                    sb.append(getUserClause());
0819:                    }
0820:                    if (debug >= 10)
0821:                    log("Query to read the user record is : " + sb.toString());
0822:                    preparedCredentials = dbConnection.prepareStatement(sb.toString());
0823:                     */
0824:                    preparedCredentials = dbConnection
0825:                            .prepareStatement(preparedCredentialsSB.toString());
0826:                }
0827:
0828:                preparedCredentials.setString(1, username);
0829:                return (preparedCredentials);
0830:
0831:            }
0832:
0833:            /** Return a short name for this Realm implementation.
0834:             * @return Short name for this Realm implementation
0835:             */
0836:            protected String getName() {
0837:
0838:                return (this .name);
0839:
0840:            }
0841:
0842:            /** <B>Not Implemented</B> - Return the password associated with the given principal's user name.
0843:             *
0844:             * @param username User's Name
0845:             * @return Returns null in all cases
0846:             */
0847:            protected String getPassword(String username) {
0848:
0849:                return (null);
0850:
0851:            }
0852:
0853:            /** <B>Not Implemented</B> - Return the Principal associated with the given user name.
0854:             * @param username User's Name
0855:             * @return Returns null in all cases
0856:             */
0857:            protected Principal getPrincipal(String username) {
0858:
0859:                return (null);
0860:
0861:            }
0862:
0863:            /** Open (if necessary) and return a database connection for use by
0864:             * this Realm. Tries to use a data source if defined, otherwise open
0865:             * a direct connection using the specified database driver
0866:             *
0867:             * @exception SQLException if a database error occurs
0868:             * @return Connection to the database
0869:             */
0870:            protected Connection open() throws SQLException {
0871:                if (dataSourceName != null) {
0872:                    // Get Connection From Data Source
0873:                    try {
0874:                        StandardServer server = (StandardServer) ServerFactory
0875:                                .getServer();
0876:                        Context context = server.getGlobalNamingContext();
0877:                        DataSource dataSource = (DataSource) context
0878:                                .lookup(dataSourceName);
0879:                        return dataSource.getConnection();
0880:                    } catch (Exception e) {
0881:                        // Log the problem for posterity
0882:                        log(sm.getString("jdbcEncryptionRealm.error.open"), e);
0883:                        return null;
0884:                    }
0885:                } else {
0886:                    // Establish Connection, or return cached one...
0887:
0888:                    // Do nothing if there is a database connection already open
0889:                    if (dbConnection != null)
0890:                        return (dbConnection);
0891:
0892:                    // Instantiate our database driver if necessary
0893:                    if (driver == null) {
0894:                        try {
0895:                            Class clazz = Class.forName(driverName);
0896:                            driver = (Driver) clazz.newInstance();
0897:                        } catch (Throwable e) {
0898:                            log(sm.getString(
0899:                                    "jdbcEncryptionRealm.error.driver", e
0900:                                            .getMessage()), e);
0901:                            //log("Can't Create Database Driver Class: Reason - " + e.getMessage());
0902:                            throw new SQLException(e.getMessage());
0903:                        }
0904:                    }
0905:
0906:                    // Open a new connection
0907:                    Properties props = new Properties();
0908:                    if (connectionName != null)
0909:                        props.put("user", connectionName);
0910:                    if (connectionPassword != null)
0911:                        props.put("password", connectionPassword);
0912:                    dbConnection = driver.connect(connectionURL, props);
0913:                    dbConnection.setAutoCommit(false);
0914:                    return (dbConnection);
0915:                }
0916:            }
0917:
0918:            /** Release our use of this connection so that it can be recycled. Only puts the connection
0919:             * back in the pool if using a DataSource, otherwise the connection is held open.
0920:             *
0921:             * @param dbConnection Connection to release
0922:             * @throws SQLException If there is an error with the database
0923:             */
0924:            protected void release(Connection dbConnection) throws SQLException {
0925:                if (!dbConnection.getAutoCommit()) {
0926:                    dbConnection.commit();
0927:                }
0928:                // Release connection if we are using a data source.
0929:                if (dataSourceName != null) {
0930:                    // Release the database connection we just used
0931:                    close(dbConnection);
0932:                }
0933:            }
0934:
0935:            /** Return a PreparedStatement configured to perform the SELECT required
0936:             * to retrieve user roles for the specified username.
0937:             *
0938:             * @param dbConnection The database connection to be used
0939:             * @param username Username for which roles should be retrieved
0940:             * @exception SQLException if a database error occurs
0941:             * @return PreparedStatement to read user's roles
0942:             */
0943:            protected PreparedStatement roles(Connection dbConnection,
0944:                    String username) throws SQLException {
0945:
0946:                if (preparedRoles == null) {
0947:                    /*
0948:                    if(this.roleSelect == null) {
0949:                    StringBuffer sb = new StringBuffer("SELECT ");
0950:                    sb.append(roleNameCol);
0951:                    sb.append(" FROM ");
0952:                    sb.append(userRoleTable);
0953:                    sb.append(" WHERE ");
0954:                    sb.append(userNameCol);
0955:                    sb.append(" = ?");
0956:                    preparedRoles = dbConnection.prepareStatement(sb.toString());
0957:                    } else
0958:                    preparedRoles = dbConnection.prepareStatement(this.roleSelect);
0959:                     */
0960:                    preparedRoles = dbConnection
0961:                            .prepareStatement(preparedRolesSB.toString());
0962:                }
0963:
0964:                preparedRoles.setString(1, username);
0965:                return (preparedRoles);
0966:
0967:            }
0968:
0969:            // ------------------------------------------------------ Lifecycle Methods
0970:
0971:            /**
0972:             * Prepare for active use of the public methods of this Component.
0973:             *
0974:             * @exception LifecycleException if this component detects a fatal error
0975:             *  that prevents it from being started */
0976:            public void start() throws LifecycleException {
0977:
0978:                // Validate that we can open our connection
0979:                try {
0980:                    Connection dbConnection = open();
0981:                    if (dbConnection != null)
0982:                        release(dbConnection);
0983:                    //else
0984:                    //    throw new LifecycleException(sm.getString("jdbcEncryptionRealm.error.openNull"));
0985:                } catch (SQLException e) {
0986:                    throw new LifecycleException(sm
0987:                            .getString("jdbcEncryptionRealm.error.open"), e);
0988:                }
0989:
0990:                // Get a reference to the Method that will be used for password Encryption
0991:                if (this .encryptionClass != null) {
0992:                    if (this .encryptionMethod == null)
0993:                        throw new LifecycleException(sm.getString(
0994:                                "jdbcEncryptionRealm.error.param",
0995:                                encryptionMethod));
0996:                    if (debug >= 10)
0997:                        log(sm.getString("jdbcEncryptionRealm.debug.classOK"));
0998:
0999:                    // look up the method with the single input string first
1000:                    try {
1001:                        Class ec = Class.forName(this .encryptionClass);
1002:                        eMethod = null;
1003:                        try {
1004:                            eMethod = ec.getMethod(this .encryptionMethod,
1005:                                    new Class[] { String.class });
1006:                        } catch (Exception e) {
1007:                            try {
1008:                                eMethod = ec.getMethod(this .encryptionMethod,
1009:                                        new Class[] { String.class,
1010:                                                String.class });
1011:                            } catch (Exception e2) {
1012:                            }
1013:                        }
1014:
1015:                        if (eMethod == null
1016:                                || !eMethod.getReturnType()
1017:                                        .equals(String.class)
1018:                                || !Modifier.isPublic(eMethod.getModifiers())
1019:                                || !Modifier.isStatic(eMethod.getModifiers())) {
1020:                            throw new LifecycleException(sm
1021:                                    .getString(
1022:                                            "jdbcEncryptionRealm.error.method",
1023:                                            this .encryptionClass,
1024:                                            this .encryptionMethod));
1025:                        }
1026:
1027:                    } catch (ClassNotFoundException e) {
1028:                        throw new LifecycleException(sm.getString(
1029:                                "jdbcEncryptionRealm.error.class",
1030:                                this .encryptionClass));
1031:                    }
1032:
1033:                    if (debug >= 10)
1034:                        log(sm.getString("jdbcEncryptionRealm.debug.methodOK"));
1035:
1036:                }
1037:
1038:                // Create the roles PreparedStatement string
1039:                /*
1040:                preparedRolesSB = new StringBuffer("SELECT ");
1041:                preparedRolesSB.append(roleNameCol);
1042:                preparedRolesSB.append(" FROM ");
1043:                preparedRolesSB.append(userRoleTable);
1044:                preparedRolesSB.append(" WHERE ");
1045:                preparedRolesSB.append(userNameCol);
1046:                preparedRolesSB.append(" = ?");
1047:                 */
1048:                if (this .roleSelect == null) {
1049:                    preparedRolesSB = new StringBuffer("SELECT ");
1050:                    preparedRolesSB.append(roleNameCol);
1051:                    preparedRolesSB.append(" FROM ");
1052:                    preparedRolesSB.append(userRoleTable);
1053:                    preparedRolesSB.append(" WHERE ");
1054:                    preparedRolesSB.append(userNameCol);
1055:                    preparedRolesSB.append(" = ?");
1056:                } else
1057:                    preparedRolesSB = new StringBuffer(this .roleSelect);
1058:                if (debug >= 10)
1059:                    log(sm.getString("jdbcEncryptionRealm.debug.roleQuery",
1060:                            preparedRolesSB.toString()));
1061:
1062:                // Create the credentials PreparedStatement string
1063:                preparedCredentialsSB = new StringBuffer("SELECT ");
1064:                preparedCredentialsSB.append(userCredCol);
1065:                preparedCredentialsSB.append(" FROM ");
1066:                preparedCredentialsSB.append(userTable);
1067:                preparedCredentialsSB.append(" WHERE ");
1068:                preparedCredentialsSB.append(userNameCol);
1069:                preparedCredentialsSB.append(" = ?");
1070:                if (getUserClause() != null) {
1071:                    preparedCredentialsSB.append(" AND ");
1072:                    preparedCredentialsSB.append(getUserClause());
1073:                }
1074:                if (debug >= 10)
1075:                    log(sm.getString("jdbcEncryptionRealm.debug.userQuery",
1076:                            preparedCredentialsSB.toString()));
1077:
1078:                // Perform normal superclass initialization
1079:                super .start();
1080:            }
1081:
1082:            /** Gracefully shut down active use of the public methods of this Component.
1083:             *
1084:             * @exception LifecycleException if this component detects a fatal error
1085:             *  that needs to be reported */
1086:            public void stop() throws LifecycleException {
1087:
1088:                // Perform normal superclass finalization
1089:                super .stop();
1090:
1091:                // Close any open DB connection
1092:                close(this.dbConnection);
1093:
1094:            }
1095:
1096:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.