]> WPIA git - gigi.git/blobdiff - lib/jetty/org/eclipse/jetty/security/JDBCLoginService.java
Importing upstream Jetty jetty-9.2.1.v20140609
[gigi.git] / lib / jetty / org / eclipse / jetty / security / JDBCLoginService.java
diff --git a/lib/jetty/org/eclipse/jetty/security/JDBCLoginService.java b/lib/jetty/org/eclipse/jetty/security/JDBCLoginService.java
new file mode 100644 (file)
index 0000000..30b0a83
--- /dev/null
@@ -0,0 +1,297 @@
+//
+//  ========================================================================
+//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+//  ------------------------------------------------------------------------
+//  All rights reserved. This program and the accompanying materials
+//  are made available under the terms of the Eclipse Public License v1.0
+//  and Apache License v2.0 which accompanies this distribution.
+//
+//      The Eclipse Public License is available at
+//      http://www.eclipse.org/legal/epl-v10.html
+//
+//      The Apache License v2.0 is available at
+//      http://www.opensource.org/licenses/apache2.0.php
+//
+//  You may elect to redistribute this code under either of these licenses.
+//  ========================================================================
+//
+
+package org.eclipse.jetty.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.security.Credential;
+
+/* ------------------------------------------------------------ */
+/**
+ * HashMapped User Realm with JDBC as data source. JDBCLoginService extends
+ * HashULoginService and adds a method to fetch user information from database.
+ * The login() method checks the inherited Map for the user. If the user is not
+ * found, it will fetch details from the database and populate the inherited
+ * Map. It then calls the superclass login() method to perform the actual
+ * authentication. Periodically (controlled by configuration parameter),
+ * internal hashes are cleared. Caching can be disabled by setting cache refresh
+ * interval to zero. Uses one database connection that is initialized at
+ * startup. Reconnect on failures. authenticate() is 'synchronized'.
+ * 
+ * An example properties file for configuration is in
+ * $JETTY_HOME/etc/jdbcRealm.properties
+ * 
+ * @version $Id: JDBCLoginService.java 4792 2009-03-18 21:55:52Z gregw $
+ * 
+ * 
+ * 
+ * 
+ */
+
+public class JDBCLoginService extends MappedLoginService
+{
+    private static final Logger LOG = Log.getLogger(JDBCLoginService.class);
+
+    protected String _config;
+    protected String _jdbcDriver;
+    protected String _url;
+    protected String _userName;
+    protected String _password;
+    protected String _userTableKey;
+    protected String _userTablePasswordField;
+    protected String _roleTableRoleField;
+    protected int _cacheTime;
+    protected long _lastHashPurge;
+    protected Connection _con;
+    protected String _userSql;
+    protected String _roleSql;
+
+
+    /* ------------------------------------------------------------ */
+    public JDBCLoginService()
+        throws IOException
+    {
+    }
+    
+    /* ------------------------------------------------------------ */
+    public JDBCLoginService(String name)
+        throws IOException
+    {
+        setName(name);
+    }
+    
+    /* ------------------------------------------------------------ */
+    public JDBCLoginService(String name, String config)
+        throws IOException
+    {
+        setName(name);
+        setConfig(config);
+    }
+    
+    /* ------------------------------------------------------------ */
+    public JDBCLoginService(String name, IdentityService identityService, String config)
+        throws IOException
+    {
+        setName(name);
+        setIdentityService(identityService);
+        setConfig(config);
+    }
+
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @see org.eclipse.jetty.security.MappedLoginService#doStart()
+     */
+    @Override
+    protected void doStart() throws Exception
+    {
+        Properties properties = new Properties();
+        Resource resource = Resource.newResource(_config);
+        try (InputStream in = resource.getInputStream())
+        {
+            properties.load(in);
+        }
+        _jdbcDriver = properties.getProperty("jdbcdriver");
+        _url = properties.getProperty("url");
+        _userName = properties.getProperty("username");
+        _password = properties.getProperty("password");
+        String _userTable = properties.getProperty("usertable");
+        _userTableKey = properties.getProperty("usertablekey");
+        String _userTableUserField = properties.getProperty("usertableuserfield");
+        _userTablePasswordField = properties.getProperty("usertablepasswordfield");
+        String _roleTable = properties.getProperty("roletable");
+        String _roleTableKey = properties.getProperty("roletablekey");
+        _roleTableRoleField = properties.getProperty("roletablerolefield");
+        String _userRoleTable = properties.getProperty("userroletable");
+        String _userRoleTableUserKey = properties.getProperty("userroletableuserkey");
+        String _userRoleTableRoleKey = properties.getProperty("userroletablerolekey");
+        _cacheTime = new Integer(properties.getProperty("cachetime"));
+
+        if (_jdbcDriver == null || _jdbcDriver.equals("")
+            || _url == null
+            || _url.equals("")
+            || _userName == null
+            || _userName.equals("")
+            || _password == null
+            || _cacheTime < 0)
+        {
+            LOG.warn("UserRealm " + getName() + " has not been properly configured");
+        }
+        _cacheTime *= 1000;
+        _lastHashPurge = 0;
+        _userSql = "select " + _userTableKey + "," + _userTablePasswordField + " from " + _userTable + " where " + _userTableUserField + " = ?";
+        _roleSql = "select r." + _roleTableRoleField
+                   + " from "
+                   + _roleTable
+                   + " r, "
+                   + _userRoleTable
+                   + " u where u."
+                   + _userRoleTableUserKey
+                   + " = ?"
+                   + " and r."
+                   + _roleTableKey
+                   + " = u."
+                   + _userRoleTableRoleKey;
+        
+        Loader.loadClass(this.getClass(), _jdbcDriver).newInstance();
+        super.doStart();
+    }
+
+
+    /* ------------------------------------------------------------ */
+    public String getConfig()
+    {
+        return _config;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * Load JDBC connection configuration from properties file.
+     * 
+     * @param config Filename or url of user properties file.
+     */
+    public void setConfig(String config)
+    {        
+        if (isRunning())
+            throw new IllegalStateException("Running");
+        _config=config;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * (re)Connect to database with parameters setup by loadConfig()
+     */
+    public void connectDatabase()
+    {
+        try
+        {
+            Class.forName(_jdbcDriver);
+            _con = DriverManager.getConnection(_url, _userName, _password);
+        }
+        catch (SQLException e)
+        {
+            LOG.warn("UserRealm " + getName() + " could not connect to database; will try later", e);
+        }
+        catch (ClassNotFoundException e)
+        {
+            LOG.warn("UserRealm " + getName() + " could not connect to database; will try later", e);
+        }
+    }
+
+    /* ------------------------------------------------------------ */
+    @Override
+    public UserIdentity login(String username, Object credentials)
+    {
+        long now = System.currentTimeMillis();
+        if (now - _lastHashPurge > _cacheTime || _cacheTime == 0)
+        {
+            _users.clear();
+            _lastHashPurge = now;
+            closeConnection();
+        }
+        
+        return super.login(username,credentials);
+    }
+
+    /* ------------------------------------------------------------ */
+    @Override
+    protected void loadUsers()
+    {   
+    }
+    
+    /* ------------------------------------------------------------ */
+    @Override
+    protected UserIdentity loadUser(String username)
+    {
+        try
+        {
+            if (null == _con) 
+                connectDatabase();
+
+            if (null == _con) 
+                throw new SQLException("Can't connect to database");
+
+            try (PreparedStatement stat1 = _con.prepareStatement(_userSql))
+            {
+                stat1.setObject(1, username);
+                try (ResultSet rs1 = stat1.executeQuery())
+                {
+                    if (rs1.next())
+                    {
+                        int key = rs1.getInt(_userTableKey);
+                        String credentials = rs1.getString(_userTablePasswordField);
+                        List<String> roles = new ArrayList<String>();
+
+                        try (PreparedStatement stat2 = _con.prepareStatement(_roleSql))
+                        {
+                            stat2.setInt(1, key);
+                            try (ResultSet rs2 = stat2.executeQuery())
+                            {
+                                while (rs2.next())
+                                    roles.add(rs2.getString(_roleTableRoleField));
+                            }
+                        }
+                        return putUser(username, credentials, roles.toArray(new String[roles.size()]));
+                    }
+                }
+            }
+        }
+        catch (SQLException e)
+        {
+            LOG.warn("UserRealm " + getName() + " could not load user information from database", e);
+            closeConnection();
+        }
+        return null;
+    }
+    
+    /* ------------------------------------------------------------ */
+    protected UserIdentity putUser (String username, String credentials, String[] roles)
+    {
+        return putUser(username, Credential.getCredential(credentials),roles);
+    }
+    
+
+    /**
+     * Close an existing connection
+     */
+    private void closeConnection ()
+    {
+        if (_con != null)
+        {
+            if (LOG.isDebugEnabled()) LOG.debug("Closing db connection for JDBCUserRealm");
+            try { _con.close(); }catch (Exception e) {LOG.ignore(e);}
+        }
+        _con = null;
+    }
+
+}