提交 11b94d86 authored 作者: mysinmyc's avatar mysinmyc

fix and improvements

上级 10123530
...@@ -1836,7 +1836,7 @@ Is also possible to temporary assign roles to to externally authenticated users ...@@ -1836,7 +1836,7 @@ Is also possible to temporary assign roles to to externally authenticated users
</p> </p>
<p>Master user cannot be externally authenticated</p> <p>Master user cannot be externally authenticated</p>
<p> <p>
To enable external authentication on a database execute statement <code>SET AUTHENTICATOR='on'</code>. This setting in persisted on the database. To enable external authentication on a database execute statement <code>SET AUTHENTICATOR TRUE</code>. This setting in persisted on the database.
</p> </p>
<p> <p>
To connect on a database by using external credentials client must append <code>AUTHREALM=H2</code> to the database URL. <code>H2</code> To connect on a database by using external credentials client must append <code>AUTHREALM=H2</code> to the database URL. <code>H2</code>
...@@ -1857,7 +1857,7 @@ h2 { ...@@ -1857,7 +1857,7 @@ h2 {
}; };
</pre> </pre>
<p> <p>
Is it possible to specify custom authentication settings by putting <code>h2auth.xml</code> file in the classpath or by using Is it possible to specify custom authentication settings by using
JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an example of h2auth.xml file content: JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an example of h2auth.xml file content:
</p> </p>
<pre> <pre>
...@@ -1896,11 +1896,11 @@ JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an ...@@ -1896,11 +1896,11 @@ JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an
</pre> </pre>
<p> <p>
Custom credentials validators must implement the interface Custom credentials validators must implement the interface
<code>org.h2.api.CredentialsValidator</code> <code>org.h2.security.auth.CredentialsValidator</code>
</p> </p>
<p> <p>
Custom criteria for role assignments must implement the interface Custom criteria for role assignments must implement the interface
<code>org.h2.api.UserToRoleMapper</code> <code>org.h2.security.auth.UserToRoleMapper</code>
</p> </p>
<!-- [close] { --></div></td></tr></table><!-- } --><!-- analytics --></body></html> <!-- [close] { --></div></td></tr></table><!-- } --><!-- analytics --></body></html>
......
...@@ -11,7 +11,6 @@ import org.h2.security.auth.Configurable; ...@@ -11,7 +11,6 @@ import org.h2.security.auth.Configurable;
/** /**
* A class that implement this interface can be used to validate * A class that implement this interface can be used to validate
* credentials provided by client. * credentials provided by client.
* It is users by DefaultAuthenticator
*/ */
public interface CredentialsValidator extends Configurable { public interface CredentialsValidator extends Configurable {
...@@ -19,7 +18,7 @@ public interface CredentialsValidator extends Configurable { ...@@ -19,7 +18,7 @@ public interface CredentialsValidator extends Configurable {
* Validate user credential * Validate user credential
* @param authenticationInfo = authentication info * @param authenticationInfo = authentication info
* @return true if credentials are valid, otherwise false * @return true if credentials are valid, otherwise false
* @throws Exception = any exception occurred (invalid credentials or internal issue) prevent user login * @throws Exception any exception occurred (invalid credentials or internal issue) prevent user login
*/ */
boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception; boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception;
......
...@@ -15,7 +15,6 @@ import org.h2.security.auth.Configurable; ...@@ -15,7 +15,6 @@ import org.h2.security.auth.Configurable;
/** /**
* A class that implement this interface can be used during * A class that implement this interface can be used during
* authentication to map external users to database roles. * authentication to map external users to database roles.
* It is used by DefaultAuthenticator
*/ */
public interface UserToRolesMapper extends Configurable { public interface UserToRolesMapper extends Configurable {
......
...@@ -22,7 +22,7 @@ import org.h2.message.Trace; ...@@ -22,7 +22,7 @@ import org.h2.message.Trace;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.result.RowFactory; import org.h2.result.RowFactory;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.security.auth.AuthenticatorBuilder; import org.h2.security.auth.AuthenticatorFactory;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
...@@ -544,14 +544,17 @@ public class Set extends Prepared { ...@@ -544,14 +544,17 @@ public class Set extends Prepared {
} }
case SetTypes.AUTHENTICATOR: { case SetTypes.AUTHENTICATOR: {
session.getUser().checkAdmin(); session.getUser().checkAdmin();
String authenticatorString=expression.getValue(session).getString();
try { try {
database.setAuthenticator(AuthenticatorBuilder.buildAuthenticator(authenticatorString)); if (expression.getBooleanValue(session)) {
addOrUpdateSetting(name,"'"+authenticatorString+"'",0); database.setAuthenticator(AuthenticatorFactory.createAuthenticator());
} else {
database.setAuthenticator(null);
}
addOrUpdateSetting(name,stringValue,0);
} catch (Exception e) { } catch (Exception e) {
//Errors during start are ignored to allow to open the database //Errors during start are ignored to allow to open the database
if (database.isStarting()) { if (database.isStarting()) {
database.getTrace(Trace.DATABASE).error(e, "SET AUTHENTICATOR: failed to set authenticator {0} during database start",authenticatorString); database.getTrace(Trace.DATABASE).error(e, "SET AUTHENTICATOR: failed to set authenticator {0} during database start",stringValue);
} else { } else {
throw DbException.convert(e); throw DbException.convert(e);
} }
......
...@@ -275,7 +275,7 @@ public class ConnectionInfo implements Cloneable { ...@@ -275,7 +275,7 @@ public class ConnectionInfo implements Cloneable {
} }
private void preservePasswordForAuthentication(Object password) { private void preservePasswordForAuthentication(Object password) {
if ((isRemote() ==false || isSSL()) && prop.containsKey("AUTHREALM") && password!=null) { if ((!isRemote() || isSSL()) && prop.containsKey("AUTHREALM") && password!=null) {
prop.put("_PASSWORD",password); prop.put("_PASSWORD",password);
} }
} }
......
...@@ -20,7 +20,7 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -20,7 +20,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.h2.api.Authenticator;
import org.h2.api.DatabaseEventListener; import org.h2.api.DatabaseEventListener;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.JavaObjectSerializer; import org.h2.api.JavaObjectSerializer;
...@@ -44,7 +44,8 @@ import org.h2.schema.Schema; ...@@ -44,7 +44,8 @@ import org.h2.schema.Schema;
import org.h2.schema.SchemaObject; import org.h2.schema.SchemaObject;
import org.h2.schema.Sequence; import org.h2.schema.Sequence;
import org.h2.schema.TriggerObject; import org.h2.schema.TriggerObject;
import org.h2.security.auth.AuthenticatorBuilder; import org.h2.security.auth.Authenticator;
import org.h2.security.auth.AuthenticatorFactory;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileLock; import org.h2.store.FileLock;
import org.h2.store.FileLockMethod; import org.h2.store.FileLockMethod;
...@@ -2956,7 +2957,7 @@ public class Database implements DataHandler { ...@@ -2956,7 +2957,7 @@ public class Database implements DataHandler {
* @return authenticator set for database * @return authenticator set for database
*/ */
public Authenticator getAuthenticator() { public Authenticator getAuthenticator() {
return authenticator == null ? InternalAuthenticator.INSTANCE : authenticator; return authenticator;
} }
/** /**
......
...@@ -16,6 +16,7 @@ import org.h2.message.DbException; ...@@ -16,6 +16,7 @@ import org.h2.message.DbException;
import org.h2.message.Trace; import org.h2.message.Trace;
import org.h2.security.auth.AuthenticationException; import org.h2.security.auth.AuthenticationException;
import org.h2.security.auth.AuthenticationInfo; import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.Authenticator;
import org.h2.store.FileLock; import org.h2.store.FileLock;
import org.h2.store.FileLockMethod; import org.h2.store.FileLockMethod;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -92,13 +93,31 @@ public class Engine implements SessionFactory { ...@@ -92,13 +93,31 @@ public class Engine implements SessionFactory {
} }
if (user == null) { if (user == null) {
if (database.validateFilePasswordHash(cipher, ci.getFilePasswordHash())) { if (database.validateFilePasswordHash(cipher, ci.getFilePasswordHash())) {
try {
AuthenticationInfo authenticationInfo=new AuthenticationInfo(ci); if (ci.getProperty("AUTHREALM")== null) {
user = database.getAuthenticator().authenticate(authenticationInfo, database); user = database.findUser(ci.getUserName());
} catch (AuthenticationException authenticationError) { if (user != null) {
database.getTrace(Trace.DATABASE).error(authenticationError, if (!user.validateUserPasswordHash(ci.getUserPasswordHash())) {
"an error occurred during authentication; user: \"" + user = null;
ci.getUserName() + "\"",ci.getUserName()); }
}
} else {
try {
Authenticator authenticator = database.getAuthenticator();
if (authenticator==null) {
DbException er = DbException.get(ErrorCode.WRONG_USER_OR_PASSWORD);
database.getTrace(Trace.DATABASE).error(er,"no authenticator for database users");
}else {
AuthenticationInfo authenticationInfo=new AuthenticationInfo(ci);
user = database.getAuthenticator().authenticate(authenticationInfo, database);
}
} catch (AuthenticationException authenticationError) {
database.getTrace(Trace.DATABASE).error(authenticationError,
"an error occurred during authentication; user: \"" +
ci.getUserName() + "\"");
}finally {
ci.cleanAuthenticationInfo();
}
} }
} }
if (opened && (user == null || !user.isAdmin())) { if (opened && (user == null || !user.isAdmin())) {
...@@ -107,7 +126,6 @@ public class Engine implements SessionFactory { ...@@ -107,7 +126,6 @@ public class Engine implements SessionFactory {
database.setEventListener(null); database.setEventListener(null);
} }
} }
ci.cleanAuthenticationInfo();
if (user == null) { if (user == null) {
DbException er = DbException.get(ErrorCode.WRONG_USER_OR_PASSWORD); DbException er = DbException.get(ErrorCode.WRONG_USER_OR_PASSWORD);
database.getTrace(Trace.DATABASE).error(er, "wrong user or password; user: \"" + database.getTrace(Trace.DATABASE).error(er, "wrong user or password; user: \"" +
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura
*/
package org.h2.engine;
import org.h2.api.Authenticator;
import org.h2.security.auth.AuthConfigException;
import org.h2.security.auth.AuthenticationException;
import org.h2.security.auth.AuthenticationInfo;
/**
* Default authentication implementation. It validate user and password internally on database
*/
public class InternalAuthenticator implements Authenticator {
public static final InternalAuthenticator INSTANCE = new InternalAuthenticator();
@Override
public User authenticate(AuthenticationInfo authenticationInfo, Database database) throws AuthenticationException {
User user = database.findUser(authenticationInfo.getUserName());
if (user != null) {
if (!user.validateUserPasswordHash(authenticationInfo.getConnectionInfo().getUserPasswordHash())) {
user = null;
}
}
return user;
}
@Override
public void init(Database database) throws AuthConfigException {
}
}
...@@ -163,7 +163,7 @@ public abstract class RightOwner extends DbObjectBase { ...@@ -163,7 +163,7 @@ public abstract class RightOwner extends DbObjectBase {
} }
List<Role> rolesToRemove= new ArrayList<>(); List<Role> rolesToRemove= new ArrayList<>();
for (Entry<Role,Right> currentEntry : grantedRoles.entrySet()) { for (Entry<Role,Right> currentEntry : grantedRoles.entrySet()) {
if ( currentEntry.getValue().isTemporary() || currentEntry.getValue().isValid()==false) { if ( currentEntry.getValue().isTemporary() || !currentEntry.getValue().isValid()) {
rolesToRemove.add(currentEntry.getKey()); rolesToRemove.add(currentEntry.getKey());
} }
} }
......
...@@ -562,6 +562,16 @@ public class SysProperties { ...@@ -562,6 +562,16 @@ public class SysProperties {
public static final String CUSTOM_DATA_TYPES_HANDLER = public static final String CUSTOM_DATA_TYPES_HANDLER =
Utils.getProperty("h2.customDataTypesHandler", null); Utils.getProperty("h2.customDataTypesHandler", null);
/**
* System property <code>h2.authConfigFile</code>
* (default: null).<br />
* authConfigFile define the URL of configuration file
* of {@link org.h2.security.auth.DefaultAuthenticator}
*
*/
public static final String AUTH_CONFIG_FILE =
Utils.getProperty("h2.authConfigFile", null);
private static final String H2_BASE_DIR = "h2.baseDir"; private static final String H2_BASE_DIR = "h2.baseDir";
private SysProperties() { private SysProperties() {
......
...@@ -16,7 +16,7 @@ public class UserBuilder { ...@@ -16,7 +16,7 @@ public class UserBuilder {
User user = new User(database, persistent ? database.allocateObjectId() : -1, authenticationInfo.getFullyQualifiedName(), false); User user = new User(database, persistent ? database.allocateObjectId() : -1, authenticationInfo.getFullyQualifiedName(), false);
//In case of external authentication fill the password hash with random data //In case of external authentication fill the password hash with random data
user.setUserPasswordHash( authenticationInfo.getRealm()==null ? authenticationInfo.getConnectionInfo().getUserPasswordHash(): MathUtils.secureRandomBytes(64)); user.setUserPasswordHash( authenticationInfo.getRealm()==null ? authenticationInfo.getConnectionInfo().getUserPasswordHash(): MathUtils.secureRandomBytes(64));
user.setTemporary(persistent == false); user.setTemporary(!persistent);
return user; return user;
} }
......
...@@ -3,13 +3,10 @@ ...@@ -3,13 +3,10 @@
* and the EPL 1.0 (http://h2database.com/html/license.html). * and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura * Initial Developer: Alessandro Ventura
*/ */
package org.h2.api; package org.h2.security.auth;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.User; import org.h2.engine.User;
import org.h2.security.auth.AuthConfigException;
import org.h2.security.auth.AuthenticationException;
import org.h2.security.auth.AuthenticationInfo;
/** /**
* Low level interface to implement full authentication process * Low level interface to implement full authentication process
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura
*/
package org.h2.security.auth;
import org.h2.api.Authenticator;
public class AuthenticatorBuilder {
private static String getAuthenticatorClassNameFrom(String authenticatorString) {
if (authenticatorString==null) {
return null;
}
switch (authenticatorString) {
case "":
case "0":
case "no":
case "off":
case "disable":
case "false":
return null;
case "1":
case "yes":
case "on":
case "enable":
case "true":
case "default":
return "org.h2.security.auth.DefaultAuthenticator";
default:
return authenticatorString;
}
}
public static Authenticator buildAuthenticator(String authenticatorStringValue) throws Exception {
String authenticatorClassName=getAuthenticatorClassNameFrom(authenticatorStringValue);
return authenticatorClassName==null ? null : (Authenticator) Class.forName(authenticatorClassName).newInstance();
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura
*/
package org.h2.security.auth;
/**
* Authenticator factory
*/
public class AuthenticatorFactory {
public static Authenticator createAuthenticator() {
return new DefaultAuthenticator();
}
}
...@@ -10,6 +10,8 @@ import java.util.Collection; ...@@ -10,6 +10,8 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.h2.util.Utils;
/** /**
* wrapper for configuration properties * wrapper for configuration properties
*/ */
...@@ -73,14 +75,7 @@ public class ConfigProperties { ...@@ -73,14 +75,7 @@ public class ConfigProperties {
if (result == null) { if (result == null) {
return defaultValue; return defaultValue;
} }
switch (result) { return Utils.parseBoolean(name, defaultValue, true);
case "true":
case "yes":
case "1":
return true;
default:
return false;
}
} }
} }
...@@ -16,13 +16,12 @@ import java.util.Set; ...@@ -16,13 +16,12 @@ import java.util.Set;
import javax.xml.bind.JAXB; import javax.xml.bind.JAXB;
import org.h2.api.Authenticator;
import org.h2.api.CredentialsValidator; import org.h2.api.CredentialsValidator;
import org.h2.api.UserToRolesMapper; import org.h2.api.UserToRolesMapper;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.InternalAuthenticator;
import org.h2.engine.Right; import org.h2.engine.Right;
import org.h2.engine.Role; import org.h2.engine.Role;
import org.h2.engine.SysProperties;
import org.h2.engine.User; import org.h2.engine.User;
import org.h2.engine.UserBuilder; import org.h2.engine.UserBuilder;
import org.h2.message.Trace; import org.h2.message.Trace;
...@@ -31,10 +30,23 @@ import org.h2.security.auth.impl.JaasCredentialsValidator; ...@@ -31,10 +30,23 @@ import org.h2.security.auth.impl.JaasCredentialsValidator;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
* Default implementation of authenticator. Credentials (typically user id and * Default authenticator implementation.
* password) are validated by CredentialsValidators (one per realm). Rights on * <p>
* the database can be managed trough UserToRolesMapper. * When client connectionInfo contains property AUTHREALM={realName} credentials
* * (typically user id and password) are validated by
* by {@link org.h2.api.CredentialsValidator} configured for that realm.
* </p>
* <p>
* When client connectionInfo doesn't contains AUTHREALM property credentials
* are validated internally on the database
* </p>
* <p>
* Rights assignment can be managed trough {@link org.h2.api.UserToRolesMapper}
* </p>
* <p>
* Default configuration has a realm H2 that validate credentials trough JAAS api (appName=h2).
* To customize configuration set h2.authConfigFile system property to refer a valid h2auth.xml config file
* </p>
*/ */
public class DefaultAuthenticator implements Authenticator { public class DefaultAuthenticator implements Authenticator {
...@@ -65,7 +77,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -65,7 +77,7 @@ public class DefaultAuthenticator implements Authenticator {
* option is useful when the authenticator is configured at code level * option is useful when the authenticator is configured at code level
* *
* @param skipDefaultInitialization * @param skipDefaultInitialization
* = if true default initialization is skipped * if true default initialization is skipped
*/ */
public DefaultAuthenticator(boolean skipDefaultInitialization) { public DefaultAuthenticator(boolean skipDefaultInitialization) {
this.skipDefaultInitialization = skipDefaultInitialization; this.skipDefaultInitialization = skipDefaultInitialization;
...@@ -114,10 +126,8 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -114,10 +126,8 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Add an authentication realm. Realms are case insensitive * Add an authentication realm. Realms are case insensitive
* *
* @param name * @param name realm name
* = realm name * @param credentialsValidator credentials validator for realm
* @param credentialsValidator
* = credentials validator for realm
*/ */
public void addRealm(String name, CredentialsValidator credentialsValidator) { public void addRealm(String name, CredentialsValidator credentialsValidator) {
realms.put(StringUtils.toUpperEnglish(name), credentialsValidator); realms.put(StringUtils.toUpperEnglish(name), credentialsValidator);
...@@ -145,11 +155,11 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -145,11 +155,11 @@ public class DefaultAuthenticator implements Authenticator {
* *
* this method is skipped if skipDefaultInitialization is set * this method is skipped if skipDefaultInitialization is set
* Order of initialization is * Order of initialization is
* 1. Check h2auth.configurationFile system property. * <ol>
* 2. Check h2auth.xml in the classpath * <li>Check h2.authConfigFile system property.</li>
* 3. Use the default configuration hard coded * <li>Use the default configuration hard coded</li>
* initialization * </ol>
* @param database * @param database where authenticator is initialized
* @throws AuthConfigException * @throws AuthConfigException
*/ */
public void init(Database database) throws AuthConfigException { public void init(Database database) throws AuthConfigException {
...@@ -166,22 +176,13 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -166,22 +176,13 @@ public class DefaultAuthenticator implements Authenticator {
Trace trace=database.getTrace(Trace.DATABASE); Trace trace=database.getTrace(Trace.DATABASE);
URL h2AuthenticatorConfigurationUrl = null; URL h2AuthenticatorConfigurationUrl = null;
try { try {
String configFile = System.getProperty("h2auth.configurationFile", null); String configFile = SysProperties.AUTH_CONFIG_FILE;
if (configFile != null) { if (configFile != null) {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("DefaultAuthenticator.config: configuration read from system property h2auth.configurationfile={0}", configFile); trace.debug("DefaultAuthenticator.config: configuration read from system property h2auth.configurationfile={0}", configFile);
} }
h2AuthenticatorConfigurationUrl = new URL(configFile); h2AuthenticatorConfigurationUrl = new URL(configFile);
} }
if (h2AuthenticatorConfigurationUrl == null) {
h2AuthenticatorConfigurationUrl = Thread.currentThread().getContextClassLoader()
.getResource("h2auth.xml");
if (h2AuthenticatorConfigurationUrl!=null) {
if (trace.isDebugEnabled()) {
trace.debug("DefaultAuthenticator.config: configuration read from classpath {0}", h2AuthenticatorConfigurationUrl);
}
}
}
if (h2AuthenticatorConfigurationUrl == null) { if (h2AuthenticatorConfigurationUrl == null) {
if (trace.isDebugEnabled()) { if (trace.isDebugEnabled()) {
trace.debug("DefaultAuthenticator.config: default configuration"); trace.debug("DefaultAuthenticator.config: default configuration");
...@@ -214,8 +215,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -214,8 +215,7 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Configure the authenticator from a configuration file * Configure the authenticator from a configuration file
* *
* @param configUrl * @param configUrl URL of configuration file
* = URL of configuration file
* @throws Exception * @throws Exception
*/ */
public void configureFromUrl(URL configUrl) throws Exception { public void configureFromUrl(URL configUrl) throws Exception {
...@@ -267,7 +267,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -267,7 +267,7 @@ public class DefaultAuthenticator implements Authenticator {
Set<String> roles = new HashSet<>(); Set<String> roles = new HashSet<>();
for (UserToRolesMapper currentUserToRolesMapper : userToRolesMappers) { for (UserToRolesMapper currentUserToRolesMapper : userToRolesMappers) {
Collection<String> currentRoles = currentUserToRolesMapper.mapUserToRoles(authenticationInfo); Collection<String> currentRoles = currentUserToRolesMapper.mapUserToRoles(authenticationInfo);
if (currentRoles != null && currentRoles.isEmpty() == false) { if (currentRoles != null && !currentRoles.isEmpty()) {
roles.addAll(currentRoles); roles.addAll(currentRoles);
} }
} }
...@@ -300,13 +300,9 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -300,13 +300,9 @@ public class DefaultAuthenticator implements Authenticator {
@Override @Override
public final User authenticate(AuthenticationInfo authenticationInfo, Database database) public final User authenticate(AuthenticationInfo authenticationInfo, Database database)
throws AuthenticationException { throws AuthenticationException {
//Allows internal users authentication
if (authenticationInfo.getRealm()==null) {
return InternalAuthenticator.INSTANCE.authenticate(authenticationInfo, database);
}
String userName = authenticationInfo.getFullyQualifiedName(); String userName = authenticationInfo.getFullyQualifiedName();
User user = database.findUser(userName); User user = database.findUser(userName);
if (user == null && isAllowUserRegistration() == false) { if (user == null && !isAllowUserRegistration()) {
throw new AuthenticationException("User " + userName + " not found in db"); throw new AuthenticationException("User " + userName + " not found in db");
} }
CredentialsValidator validator = realms.get(authenticationInfo.getRealm()); CredentialsValidator validator = realms.get(authenticationInfo.getRealm());
...@@ -314,7 +310,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -314,7 +310,7 @@ public class DefaultAuthenticator implements Authenticator {
throw new AuthenticationException("realm " + authenticationInfo.getRealm() + " not configured"); throw new AuthenticationException("realm " + authenticationInfo.getRealm() + " not configured");
} }
try { try {
if (validator.validateCredentials(authenticationInfo) == false) { if (!validator.validateCredentials(authenticationInfo)) {
return null; return null;
} }
} catch (Exception e) { } catch (Exception e) {
......
...@@ -11,7 +11,12 @@ import org.h2.security.auth.ConfigProperties; ...@@ -11,7 +11,12 @@ import org.h2.security.auth.ConfigProperties;
/** /**
* Assign to user a role based on realm name * Assign to user a role based on realm name
* *
* by default role name is @{realm} * * <p>
* Configuration parameters:
* </p>
* <ul>
* <li> roleNameFormat, optional by default is @{realm}</li>
* </ul>
*/ */
public class AssignRealmNameRole implements UserToRolesMapper{ public class AssignRealmNameRole implements UserToRolesMapper{
......
...@@ -21,8 +21,12 @@ import org.h2.security.auth.ConfigProperties; ...@@ -21,8 +21,12 @@ import org.h2.security.auth.ConfigProperties;
/** /**
* Validate credentials by using standard Java Authentication and Authorization Service * Validate credentials by using standard Java Authentication and Authorization Service
* *
* configuration parameters: * <p>
* appName = application name inside the JAAS configuration (by default h2) * Configuration parameters:
* </p>
* <ul>
* <li>appName inside the JAAS configuration (by default h2)</li>
* </ul>
* *
*/ */
public class JaasCredentialsValidator implements CredentialsValidator { public class JaasCredentialsValidator implements CredentialsValidator {
......
...@@ -17,12 +17,15 @@ import org.h2.security.auth.ConfigProperties; ...@@ -17,12 +17,15 @@ import org.h2.security.auth.ConfigProperties;
/** /**
* Validate credentials by performing an LDAP bind * Validate credentials by performing an LDAP bind
* * <p>
* configuration parameters: * Configuration parameters:
* bindDnPattern = bind dn pattern with %u istead of username (example: uid=%u,ou=users,dc=example,dc=com) * </p>
* host = ldap host * <ul>
* port (optional) = ldap port (by default 389 for unsecure, 636 for secure) * <li>bindDnPattern bind dn pattern with %u instead of username (example: uid=%u,ou=users,dc=example,dc=com)</li>
* secure (optional) = use ssl (default true) * <li>host ldap server</li>
* <li>port of ldap service; optional, by default 389 for unsecure, 636 for secure</li>
* <li>secure, optional by default is true (use SSL)</li>
* </ul>
*/ */
public class LdapCredentialsValidator implements CredentialsValidator { public class LdapCredentialsValidator implements CredentialsValidator {
......
...@@ -16,9 +16,13 @@ import org.h2.security.auth.ConfigProperties; ...@@ -16,9 +16,13 @@ import org.h2.security.auth.ConfigProperties;
/** /**
* Assign static roles to authenticated users * Assign static roles to authenticated users
* <p>
* Configuration parameters:
* </p>
* <ul>
* <li>roles role list separated by comma</li>
* </ul>
* *
* parameters:
* roles = role list separated by comma
*/ */
public class StaticRolesMapper implements UserToRolesMapper { public class StaticRolesMapper implements UserToRolesMapper {
......
...@@ -43,7 +43,7 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -43,7 +43,7 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException { public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException {
if (userNamePattern!=null) { if (userNamePattern!=null) {
if (userNamePattern.matcher(authenticationInfo.getUserName()).matches()==false) { if (!userNamePattern.matcher(authenticationInfo.getUserName()).matches()) {
return false; return false;
} }
} }
......
...@@ -15,6 +15,7 @@ import org.h2.Driver; ...@@ -15,6 +15,7 @@ import org.h2.Driver;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.store.fs.FilePathRec; import org.h2.store.fs.FilePathRec;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.auth.TestAuthentication;
import org.h2.test.bench.TestPerformance; import org.h2.test.bench.TestPerformance;
import org.h2.test.db.TestAlter; import org.h2.test.db.TestAlter;
import org.h2.test.db.TestAlterSchemaRename; import org.h2.test.db.TestAlterSchemaRename;
...@@ -974,6 +975,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -974,6 +975,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestSampleApps()); addTest(new TestSampleApps());
addTest(new TestStringCache()); addTest(new TestStringCache());
addTest(new TestValueMemory()); addTest(new TestValueMemory());
addTest(new TestAuthentication());
runAddedTests(1); runAddedTests(1);
......
...@@ -14,6 +14,9 @@ import javax.security.auth.callback.PasswordCallback; ...@@ -14,6 +14,9 @@ import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule; import javax.security.auth.spi.LoginModule;
/**
* Dummy login module used for test cases
*/
public class MyLoginModule implements LoginModule{ public class MyLoginModule implements LoginModule{
String password; String password;
......
...@@ -104,6 +104,7 @@ public class TestAuthentication extends TestBase { ...@@ -104,6 +104,7 @@ public class TestAuthentication extends TestBase {
try { try {
configureJaas(); configureJaas();
Properties properties = new Properties(); Properties properties = new Properties();
properties.setProperty("USER", "dba");
ConnectionInfo connectionInfo = new ConnectionInfo(getDatabaseURL(), properties); ConnectionInfo connectionInfo = new ConnectionInfo(getDatabaseURL(), properties);
session = Engine.getInstance().createSession(connectionInfo); session = Engine.getInstance().createSession(connectionInfo);
database = session.getDatabase(); database = session.getDatabase();
...@@ -126,6 +127,7 @@ public class TestAuthentication extends TestBase { ...@@ -126,6 +127,7 @@ public class TestAuthentication extends TestBase {
testStaticRole(); testStaticRole();
testStaticUserCredentials(); testStaticUserCredentials();
testUserRegistration(); testUserRegistration();
testSet();
} }
protected void testInvalidPassword() throws Exception { protected void testInvalidPassword() throws Exception {
...@@ -235,4 +237,20 @@ public class TestAuthentication extends TestBase { ...@@ -235,4 +237,20 @@ public class TestAuthentication extends TestBase {
rightConnection.close(); rightConnection.close();
} }
} }
protected void testSet() throws Exception{
Connection rightConnection = DriverManager.getConnection(
getDatabaseURL()+";AUTHENTICATOR=FALSE","DBA","");
try {
try {
testExternalUser();
throw new Exception("External user shouldnt be allowed");
}catch (Exception e) {
}
} finally {
configureAuthentication(database);
rightConnection.close();
}
testExternalUser();
}
} }
\ No newline at end of file
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: Alessandro Ventura
*/
package org.h2.test.auth;
import java.util.Properties;
import javax.security.auth.login.Configuration;
import org.h2.api.Authenticator;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.Database;
import org.h2.engine.Engine;
import org.h2.engine.Role;
import org.h2.engine.User;
import org.h2.security.auth.AuthConfigException;
import org.h2.security.auth.AuthenticationException;
import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.DefaultAuthenticator;
import org.h2.security.auth.impl.JaasCredentialsValidator;
import org.h2.test.TestBase;
public class TestAuthenticationDefaults extends TestAuthentication {
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
String getRealmName() {
return DefaultAuthenticator.DEFAULT_REALMNAME;
}
@Override
String getJaasConfigName() {
return JaasCredentialsValidator.DEFAULT_APPNAME;
}
@Override
void configureAuthentication(Database database) {
database.setAuthenticator(new DefaultAuthenticator());
}
@Override
public void test() throws Exception {
Configuration oldConfiguration = Configuration.getConfiguration();
try {
configureJaas();
Properties properties = new Properties();
ConnectionInfo connectionInfo = new ConnectionInfo(getDatabaseURL(), properties);
session = Engine.getInstance().createSession(connectionInfo);
database = session.getDatabase();
configureAuthentication(database);
try {
testInvalidPassword();
testExternalUserWihoutRealm();
testExternalUser();
testAssignRealNameRole();
} finally {
session.close();
}
} finally {
Configuration.setConfiguration(oldConfiguration);
}
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论