提交 3833074b authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix long lines, missing javadoc, and other formatting

上级 74de7992
...@@ -21,13 +21,13 @@ Change Log ...@@ -21,13 +21,13 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Issue #1177: Resource leak in Recover tool <li>Issue #1177: Resource leak in Recover tool
</li> </li>
<li>PR #1183: Improve concurrency of connection pool with wait-free implement <li>PR #1183: Improve concurrency of connection pool with wait-free implement
</li> </li>
<li>Issue #1073: H2 v1.4.197 fails to open an existing database with the error [Unique index or primary key violation: "PRIMARY KEY ON """".PAGE_INDEX"] <li>Issue #1073: H2 v1.4.197 fails to open an existing database with the error [Unique index or primary key violation: "PRIMARY KEY ON """".PAGE_INDEX"]
</li> </li>
<li>PR #1179: Drop TransactionMap.readLogId <li>PR #1179: Drop TransactionMap.readLogId
</li> </li>
<li>PR #1181: Improve CURRENT_TIMESTAMP and add LOCALTIME and LOCALTIMESTAMP <li>PR #1181: Improve CURRENT_TIMESTAMP and add LOCALTIME and LOCALTIMESTAMP
</li> </li>
...@@ -79,7 +79,7 @@ Change Log ...@@ -79,7 +79,7 @@ Change Log
</li> </li>
<li>PR #1142: Misc small fixes <li>PR #1142: Misc small fixes
</li> </li>
<li>PR #1141: Assorted optimizations and fixes <li>PR #1141: Assorted optimizations and fixes
</li> </li>
<li>PR #1138, #1139: Fix a memory leak caused by DatabaseCloser objects <li>PR #1138, #1139: Fix a memory leak caused by DatabaseCloser objects
</li> </li>
......
...@@ -1835,7 +1835,7 @@ Is also possible to temporary assign roles to to externally authenticated users. ...@@ -1835,7 +1835,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 TRUE</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>
...@@ -1850,9 +1850,9 @@ JAAS login configuration file</a> content: ...@@ -1850,9 +1850,9 @@ JAAS login configuration file</a> content:
</p> </p>
<pre> <pre>
h2 { h2 {
com.sun.security.auth.module.LdapLoginModule REQUIRED \ com.sun.security.auth.module.LdapLoginModule REQUIRED \
userProvider="ldap://127.0.0.1:10389" authIdentity="uid={USERNAME},ou=people,dc=example,dc=com" \ userProvider="ldap://127.0.0.1:10389" authIdentity="uid={USERNAME},ou=people,dc=example,dc=com" \
debug=true useSSL=false ; debug=true useSSL=false ;
}; };
</pre> </pre>
<p> <p>
...@@ -1863,14 +1863,14 @@ JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an ...@@ -1863,14 +1863,14 @@ JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an
&lt;h2Auth allowUserRegistration="false" createMissingRoles="true"&gt; &lt;h2Auth allowUserRegistration="false" createMissingRoles="true"&gt;
&lt;!-- realm: DUMMY authenticate users named DUMMY[0-9] with a static password --&gt; &lt;!-- realm: DUMMY authenticate users named DUMMY[0-9] with a static password --&gt;
&lt;realm name="DUMMY" &lt;realm name="DUMMY"
validatorClass="org.h2.security.auth.impl.FixedPasswordCredentialsValidator"&gt; validatorClass="org.h2.security.auth.impl.FixedPasswordCredentialsValidator"&gt;
&lt;property name="userNamePattern" value="DUMMY[0-9]" /&gt; &lt;property name="userNamePattern" value="DUMMY[0-9]" /&gt;
&lt;property name="password" value="mock" /&gt; &lt;property name="password" value="mock" /&gt;
&lt;/realm&gt; &lt;/realm&gt;
&lt;!-- realm LDAPEXAMPLE:perform credentials validation on LDAP --&gt; &lt;!-- realm LDAPEXAMPLE:perform credentials validation on LDAP --&gt;
&lt;realm name="LDAPEXAMPLE" &lt;realm name="LDAPEXAMPLE"
validatorClass="org.h2.security.auth.impl.LdapCredentialsValidator"&gt; validatorClass="org.h2.security.auth.impl.LdapCredentialsValidator"&gt;
&lt;property name="bindDnPattern" value="uid=%u,ou=people,dc=example,dc=com" /&gt; &lt;property name="bindDnPattern" value="uid=%u,ou=people,dc=example,dc=com" /&gt;
&lt;property name="host" value="127.0.0.1" /&gt; &lt;property name="host" value="127.0.0.1" /&gt;
...@@ -1879,7 +1879,7 @@ JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an ...@@ -1879,7 +1879,7 @@ JVM argument <code>-Dh2auth.configurationFile={urlOfH2Auth.xml}</code>. Here an
&lt;/realm&gt; &lt;/realm&gt;
&lt;!-- realm JAAS: perform credentials validation by using JAAS api --&gt; &lt;!-- realm JAAS: perform credentials validation by using JAAS api --&gt;
&lt;realm name="JAAS" &lt;realm name="JAAS"
validatorClass="org.h2.security.auth.impl.JaasCredentialsValidator"&gt; validatorClass="org.h2.security.auth.impl.JaasCredentialsValidator"&gt;
&lt;property name="appName" value="H2" /&gt; &lt;property name="appName" value="H2" /&gt;
&lt;/realm&gt; &lt;/realm&gt;
......
...@@ -9,19 +9,23 @@ import org.h2.security.auth.AuthenticationInfo; ...@@ -9,19 +9,23 @@ import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.Configurable; 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
* credentials provided by client. * provided by client.
* <p> * <p>
* <b>This feature is experimental and subject to change</b> * <b>This feature is experimental and subject to change</b>
* </p> * </p>
*/ */
public interface CredentialsValidator extends Configurable { 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;
......
...@@ -1993,15 +1993,15 @@ public class ErrorCode { ...@@ -1993,15 +1993,15 @@ public class ErrorCode {
* The error with code <code>90144</code> is thrown when * The error with code <code>90144</code> is thrown when
* user trying to login into a database with AUTHREALM set and * user trying to login into a database with AUTHREALM set and
* the target database doesn't have an authenticator defined * the target database doesn't have an authenticator defined
* <p>Authenticator experimental feature can be enabled by * <p>Authenticator experimental feature can be enabled by
* </p> * </p>
* <pre> * <pre>
* SET AUTHENTICATOR TRUE * SET AUTHENTICATOR TRUE
* </pre> * </pre>
*/ */
public static final int AUTHENTICATOR_NOT_AVAILABLE = 90144; public static final int AUTHENTICATOR_NOT_AVAILABLE = 90144;
// next are 90122, 90145 // next are 90122, 90145
private ErrorCode() { private ErrorCode() {
......
...@@ -12,19 +12,22 @@ import org.h2.security.auth.AuthenticationInfo; ...@@ -12,19 +12,22 @@ import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.Configurable; 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
* authentication to map external users to database roles. * map external users to database roles.
* <p> * <p>
* <b>This feature is experimental and subject to change</b> * <b>This feature is experimental and subject to change</b>
* </p> * </p>
*/ */
public interface UserToRolesMapper extends Configurable { public interface UserToRolesMapper extends Configurable {
/** /**
* Map user identified by authentication info to a set of granted roles * Map user identified by authentication info to a set of granted roles.
*
* @param authenticationInfo * @param authenticationInfo
* authentication information
* @return list of roles to be assigned to the user temporary * @return list of roles to be assigned to the user temporary
* @throws AuthenticationException * @throws AuthenticationException
* on authentication exception
*/ */
Collection<String> mapUserToRoles(AuthenticationInfo authenticationInfo) throws AuthenticationException; Collection<String> mapUserToRoles(AuthenticationInfo authenticationInfo) throws AuthenticationException;
} }
...@@ -548,9 +548,10 @@ public class Set extends Prepared { ...@@ -548,9 +548,10 @@ public class Set extends Prepared {
} }
addOrUpdateSetting(name,expression.getValue(session).getString(),0); addOrUpdateSetting(name,expression.getValue(session).getString(),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, "{0}: failed to set authenticator during database start ",expression.toString()); database.getTrace(Trace.DATABASE).error(e,
"{0}: failed to set authenticator during database start ", expression.toString());
} else { } else {
throw DbException.convert(e); throw DbException.convert(e);
} }
......
...@@ -76,7 +76,7 @@ public class ConnectionInfo implements Cloneable { ...@@ -76,7 +76,7 @@ public class ConnectionInfo implements Cloneable {
setUserName(removeProperty("USER", "")); setUserName(removeProperty("USER", ""));
name = url.substring(Constants.START_URL.length()); name = url.substring(Constants.START_URL.length());
parseName(); parseName();
convertPasswords(); convertPasswords();
String recoverTest = removeProperty("RECOVER_TEST", null); String recoverTest = removeProperty("RECOVER_TEST", null);
if (recoverTest != null) { if (recoverTest != null) {
FilePathRec.register(); FilePathRec.register();
...@@ -279,7 +279,7 @@ public class ConnectionInfo implements Cloneable { ...@@ -279,7 +279,7 @@ public class ConnectionInfo implements Cloneable {
prop.put("AUTHZPWD",password instanceof char[] ? new String((char[])password) : password); prop.put("AUTHZPWD",password instanceof char[] ? new String((char[])password) : password);
} }
} }
private char[] removePassword() { private char[] removePassword() {
Object p = prop.remove("PASSWORD"); Object p = prop.remove("PASSWORD");
preservePasswordForAuthentication(p); preservePasswordForAuthentication(p);
...@@ -664,6 +664,9 @@ public class ConnectionInfo implements Cloneable { ...@@ -664,6 +664,9 @@ public class ConnectionInfo implements Cloneable {
return url; return url;
} }
/**
* Clear authentication properties.
*/
public void cleanAuthenticationInfo() { public void cleanAuthenticationInfo() {
removeProperty("AUTHREALM", false); removeProperty("AUTHREALM", false);
removeProperty("AUTHZPWD", false); removeProperty("AUTHZPWD", false);
......
...@@ -2983,7 +2983,7 @@ public class Database implements DataHandler { ...@@ -2983,7 +2983,7 @@ public class Database implements DataHandler {
/** /**
* Set current database authenticator * Set current database authenticator
* *
* @param authenticator = authenticator to set, null to revert to the Internal authenticator * @param authenticator = authenticator to set, null to revert to the Internal authenticator
*/ */
public void setAuthenticator(Authenticator authenticator) { public void setAuthenticator(Authenticator authenticator) {
......
...@@ -153,9 +153,9 @@ public abstract class RightOwner extends DbObjectBase { ...@@ -153,9 +153,9 @@ public abstract class RightOwner extends DbObjectBase {
grantedRoles = null; grantedRoles = null;
} }
} }
/** /**
* Remove all the temporary rights granted on roles * Remove all the temporary rights granted on roles
*/ */
public void revokeTemporaryRightsOnRoles() { public void revokeTemporaryRightsOnRoles() {
if (grantedRoles == null) { if (grantedRoles == null) {
...@@ -171,8 +171,8 @@ public abstract class RightOwner extends DbObjectBase { ...@@ -171,8 +171,8 @@ public abstract class RightOwner extends DbObjectBase {
revokeRole(currentRoleToRemove); revokeRole(currentRoleToRemove);
} }
} }
/** /**
* Get the 'grant schema' right of this object. * Get the 'grant schema' right of this object.
......
...@@ -560,11 +560,11 @@ public class SysProperties { ...@@ -560,11 +560,11 @@ public class SysProperties {
* (default: null).<br /> * (default: null).<br />
* authConfigFile define the URL of configuration file * authConfigFile define the URL of configuration file
* of {@link org.h2.security.auth.DefaultAuthenticator} * of {@link org.h2.security.auth.DefaultAuthenticator}
* *
*/ */
public static final String AUTH_CONFIG_FILE = public static final String AUTH_CONFIG_FILE =
Utils.getProperty("h2.authConfigFile", null); 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() {
......
...@@ -475,14 +475,19 @@ public class Transaction { ...@@ -475,14 +475,19 @@ public class Transaction {
public boolean waitFor(Transaction toWaitFor) { public boolean waitFor(Transaction toWaitFor) {
if (isDeadlocked(toWaitFor)) { if (isDeadlocked(toWaitFor)) {
StringBuilder details = new StringBuilder(String.format("Transaction %d has been chosen as a deadlock victim. Details:%n", transactionId)); StringBuilder details = new StringBuilder(
for(Transaction tx = toWaitFor, nextTx; (nextTx = tx.blockingTransaction) != null; tx = nextTx) { String.format("Transaction %d has been chosen as a deadlock victim. Details:%n", transactionId));
details.append(String.format("Transaction %d attempts to update map <%s> entry with key <%s> modified by transaction %s%n", for (Transaction tx = toWaitFor, nextTx; (nextTx = tx.blockingTransaction) != null; tx = nextTx) {
details.append(String.format(
"Transaction %d attempts to update map <%s> entry with key <%s> modified by transaction %s%n",
tx.transactionId, tx.blockingMap.getName(), tx.blockingKey, tx.blockingTransaction)); tx.transactionId, tx.blockingMap.getName(), tx.blockingKey, tx.blockingTransaction));
if (nextTx == this) { if (nextTx == this) {
details.append(String.format("Transaction %d attempts to update map <%s> entry with key <%s> modified by transaction %s%n", details.append(String.format(
"Transaction %d attempts to update map <%s> entry with key <%s>"
+ " modified by transaction %s%n",
transactionId, blockingMap.getName(), blockingKey, toWaitFor)); transactionId, blockingMap.getName(), blockingKey, toWaitFor));
throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTIONS_DEADLOCK, details.toString()); throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTIONS_DEADLOCK,
details.toString());
} }
} }
} }
......
...@@ -130,7 +130,8 @@ public class TransactionMap<K, V> { ...@@ -130,7 +130,8 @@ public class TransactionMap<K, V> {
} }
} }
} else { } else {
// The undo logs are much smaller than the map - scan all undo logs, and then lookup relevant map entry. // The undo logs are much smaller than the map - scan all undo logs,
// and then lookup relevant map entry.
for (MVMap.RootReference undoLogRootReference : undoLogRootReferences) { for (MVMap.RootReference undoLogRootReference : undoLogRootReferences) {
if (undoLogRootReference != null) { if (undoLogRootReference != null) {
Cursor<Long, Object[]> cursor = new Cursor<>(undoLogRootReference.root, null); Cursor<Long, Object[]> cursor = new Cursor<>(undoLogRootReference.root, null);
...@@ -139,12 +140,15 @@ public class TransactionMap<K, V> { ...@@ -139,12 +140,15 @@ public class TransactionMap<K, V> {
Object op[] = cursor.getValue(); Object op[] = cursor.getValue();
if ((int) op[0] == map.getId()) { if ((int) op[0] == map.getId()) {
VersionedValue currentValue = map.get(mapRootPage, op[1]); VersionedValue currentValue = map.get(mapRootPage, op[1]);
// If map entry is not there, then we never counted it, in the first place, so skip it. // If map entry is not there, then we never counted
// This is possible when undo entry exists because it belongs // it, in the first place, so skip it.
// to a committed but not yet closed transaction, // This is possible when undo entry exists because
// and it was later deleted by some other already committed and closed transaction. // it belongs to a committed but not yet closed
// transaction, and it was later deleted by some
// other already committed and closed transaction.
if (currentValue != null) { if (currentValue != null) {
// only the last undo entry for any given map key should be considered // only the last undo entry for any given map
// key should be considered
long operationId = cursor.getKey(); long operationId = cursor.getKey();
if (currentValue.getOperationId() == operationId) { if (currentValue.getOperationId() == operationId) {
int txId = TransactionStore.getTransactionId(operationId); int txId = TransactionStore.getTransactionId(operationId);
...@@ -204,7 +208,8 @@ public class TransactionMap<K, V> { ...@@ -204,7 +208,8 @@ public class TransactionMap<K, V> {
*/ */
public V putIfAbsent(K key, V value) { public V putIfAbsent(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null"); DataUtils.checkArgument(value != null, "The value may not be null");
TxDecisionMaker decisionMaker = new TxDecisionMaker.PutIfAbsentDecisionMaker(map.getId(), key, value, transaction); TxDecisionMaker decisionMaker = new TxDecisionMaker.PutIfAbsentDecisionMaker(map.getId(), key, value,
transaction);
return set(key, decisionMaker); return set(key, decisionMaker);
} }
...@@ -275,8 +280,10 @@ public class TransactionMap<K, V> { ...@@ -275,8 +280,10 @@ public class TransactionMap<K, V> {
} while (blockingTransaction.sequenceNum > sequenceNumWhenStarted || transaction.waitFor(blockingTransaction)); } while (blockingTransaction.sequenceNum > sequenceNumWhenStarted || transaction.waitFor(blockingTransaction));
throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTION_LOCKED, throw DataUtils.newIllegalStateException(DataUtils.ERROR_TRANSACTION_LOCKED,
"Map entry <{0}> with key <{1}> and value {2} is locked by tx {3} and can not be updated by tx {4} within allocated time interval {5} ms.", "Map entry <{0}> with key <{1}> and value {2} is locked by tx {3} and can not be updated by tx {4}"
map.getName(), key, result, blockingTransaction.transactionId, transaction.transactionId, transaction.timeoutMillis); + " within allocated time interval {5} ms.",
map.getName(), key, result, blockingTransaction.transactionId, transaction.transactionId,
transaction.timeoutMillis);
} }
/** /**
...@@ -319,7 +326,8 @@ public class TransactionMap<K, V> { ...@@ -319,7 +326,8 @@ public class TransactionMap<K, V> {
*/ */
public boolean trySet(K key, V value) { public boolean trySet(K key, V value) {
try { try {
// TODO: effective transaction.timeoutMillis should be set to 0 here and restored before return // TODO: effective transaction.timeoutMillis should be set to 0 here
// and restored before return
// TODO: eliminate exception usage as part of normal control flaw // TODO: eliminate exception usage as part of normal control flaw
set(key, value); set(key, value);
return true; return true;
......
...@@ -168,7 +168,8 @@ public class TransactionStore { ...@@ -168,7 +168,8 @@ public class TransactionStore {
assert committed || lastUndoKey != null; assert committed || lastUndoKey != null;
assert committed || getTransactionId(lastUndoKey) == transactionId; assert committed || getTransactionId(lastUndoKey) == transactionId;
long logId = lastUndoKey == null ? 0 : getLogId(lastUndoKey) + 1; long logId = lastUndoKey == null ? 0 : getLogId(lastUndoKey) + 1;
registerTransaction(transactionId, status, name, logId, timeoutMillis, 0, RollbackListener.NONE); registerTransaction(transactionId, status, name, logId, timeoutMillis, 0,
RollbackListener.NONE);
} }
} }
} }
...@@ -305,7 +306,7 @@ public class TransactionStore { ...@@ -305,7 +306,7 @@ public class TransactionStore {
timeoutMillis = this.timeoutMillis; timeoutMillis = this.timeoutMillis;
} }
Transaction transaction = registerTransaction(0, Transaction.STATUS_OPEN, null, 0, Transaction transaction = registerTransaction(0, Transaction.STATUS_OPEN, null, 0,
timeoutMillis, ownerId, listener); timeoutMillis, ownerId, listener);
return transaction; return transaction;
} }
...@@ -336,7 +337,7 @@ public class TransactionStore { ...@@ -336,7 +337,7 @@ public class TransactionStore {
} while(!success); } while(!success);
Transaction transaction = new Transaction(this, transactionId, sequenceNo, status, name, logId, Transaction transaction = new Transaction(this, transactionId, sequenceNo, status, name, logId,
timeoutMillis, ownerId, listener); timeoutMillis, ownerId, listener);
assert transactions.get(transactionId) == null; assert transactions.get(transactionId) == null;
transactions.set(transactionId, transaction); transactions.set(transactionId, transaction);
......
...@@ -15,9 +15,9 @@ import org.h2.mvstore.MVMap; ...@@ -15,9 +15,9 @@ import org.h2.mvstore.MVMap;
public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> { public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue> {
private final int mapId; private final int mapId;
private final Object key; private final Object key;
final Object value; final Object value;
private final Transaction transaction; private final Transaction transaction;
long undoKey; long undoKey;
private Transaction blockingTransaction; private Transaction blockingTransaction;
private MVMap.Decision decision; private MVMap.Decision decision;
...@@ -52,7 +52,8 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue ...@@ -52,7 +52,8 @@ public abstract class TxDecisionMaker extends MVMap.DecisionMaker<VersionedValue
// condition above means transaction has been committed/rplled back and closed by now // condition above means transaction has been committed/rplled back and closed by now
decision = MVMap.Decision.REPEAT; decision = MVMap.Decision.REPEAT;
} else { } else {
// this entry comes from a different transaction, and this transaction is not committed yet // this entry comes from a different transaction, and this
// transaction is not committed yet
// should wait on blockingTransaction that was determined earlier // should wait on blockingTransaction that was determined earlier
decision = MVMap.Decision.ABORT; decision = MVMap.Decision.ABORT;
} }
......
...@@ -107,7 +107,7 @@ public class VersionedValue { ...@@ -107,7 +107,7 @@ public class VersionedValue {
if(obj == null) return 0; if(obj == null) return 0;
VersionedValue v = (VersionedValue) obj; VersionedValue v = (VersionedValue) obj;
int res = Constants.MEMORY_OBJECT + 8 + 2 * Constants.MEMORY_POINTER + int res = Constants.MEMORY_OBJECT + 8 + 2 * Constants.MEMORY_POINTER +
getValMemory(v.value); getValMemory(v.value);
if (v.getOperationId() != 0) { if (v.getOperationId() != 0) {
res += getValMemory(v.getCommittedValue()); res += getValMemory(v.getCommittedValue());
} }
......
...@@ -27,8 +27,8 @@ public class AuthenticationInfo { ...@@ -27,8 +27,8 @@ public class AuthenticationInfo {
public AuthenticationInfo(ConnectionInfo connectionInfo) { public AuthenticationInfo(ConnectionInfo connectionInfo) {
this.connectionInfo = connectionInfo; this.connectionInfo = connectionInfo;
this.realm = connectionInfo.getProperty("AUTHREALM", null); this.realm = connectionInfo.getProperty("AUTHREALM", null);
if (this.realm!=null) { if (this.realm != null) {
this.realm=StringUtils.toUpperEnglish(this.realm); this.realm = StringUtils.toUpperEnglish(this.realm);
} }
this.password = connectionInfo.getProperty("AUTHZPWD", null); this.password = connectionInfo.getProperty("AUTHZPWD", null);
} }
...@@ -50,15 +50,16 @@ public class AuthenticationInfo { ...@@ -50,15 +50,16 @@ public class AuthenticationInfo {
} }
public String getFullyQualifiedName() { public String getFullyQualifiedName() {
if (realm==null) { if (realm == null) {
return connectionInfo.getUserName(); return connectionInfo.getUserName();
} else { } else {
return connectionInfo.getUserName()+"@"+realm; return connectionInfo.getUserName() + "@" + realm;
} }
} }
/** /**
* get nested identity * get nested identity
*
* @return * @return
*/ */
public Object getNestedIdentity() { public Object getNestedIdentity() {
...@@ -66,8 +67,11 @@ public class AuthenticationInfo { ...@@ -66,8 +67,11 @@ public class AuthenticationInfo {
} }
/** /**
* Method used by authenticators to hold informations about authenticated user * Method used by authenticators to hold informations about authenticated
* @param nestedIdentity = nested identity object * user
*
* @param nestedIdentity
* = nested identity object
*/ */
public void setNestedIdentity(Object nestedIdentity) { public void setNestedIdentity(Object nestedIdentity) {
this.nestedIdentity = nestedIdentity; this.nestedIdentity = nestedIdentity;
......
...@@ -9,25 +9,27 @@ import org.h2.engine.Database; ...@@ -9,25 +9,27 @@ import org.h2.engine.Database;
import org.h2.engine.User; import org.h2.engine.User;
/** /**
* Low level interface to implement full authentication process * Low level interface to implement full authentication process.
*/ */
public interface Authenticator { public interface Authenticator {
/** /**
* perform user authentication * Perform user authentication.
* *
* @param authenticationInfo * @param authenticationInfo
* @param database * @param database
* @return valid database user or null if user doesn't exists in the database * @return valid database user or null if user doesn't exists in the
* database
* @throws AuthenticationException * @throws AuthenticationException
*/ */
User authenticate(AuthenticationInfo authenticationInfo, Database database) throws AuthenticationException; User authenticate(AuthenticationInfo authenticationInfo, Database database) throws AuthenticationException;
/** /**
* Initialize the authenticator. This method is invoked by databases when the authenticator is set * Initialize the authenticator. This method is invoked by databases when
* when the authenticator is set. * the authenticator is set when the authenticator is set.
* @param database = target database *
* @param database
* target database
* @throws AuthConfigException * @throws AuthConfigException
*/ */
void init(Database database) throws AuthConfigException; void init(Database database) throws AuthConfigException;
......
...@@ -20,19 +20,19 @@ public class ConfigProperties { ...@@ -20,19 +20,19 @@ public class ConfigProperties {
private Map<String, String> properties; private Map<String, String> properties;
public ConfigProperties() { public ConfigProperties() {
properties = new HashMap<>(); properties = new HashMap<>();
} }
public ConfigProperties(PropertyConfig...configProperties) { public ConfigProperties(PropertyConfig... configProperties) {
this(configProperties==null?null:Arrays.asList(configProperties)); this(configProperties == null ? null : Arrays.asList(configProperties));
} }
public ConfigProperties(Collection<PropertyConfig> configProperties) { public ConfigProperties(Collection<PropertyConfig> configProperties) {
properties = new HashMap<>(); properties = new HashMap<>();
if (properties != null) { if (properties != null) {
for (PropertyConfig currentProperty : configProperties) { for (PropertyConfig currentProperty : configProperties) {
if (properties.put(currentProperty.getName(), currentProperty.getValue())!=null) { if (properties.put(currentProperty.getName(), currentProperty.getValue()) != null) {
throw new AuthConfigException("duplicate property "+currentProperty.getName()); throw new AuthConfigException("duplicate property " + currentProperty.getName());
} }
} }
} }
...@@ -49,7 +49,7 @@ public class ConfigProperties { ...@@ -49,7 +49,7 @@ public class ConfigProperties {
public String getStringValue(String name) { public String getStringValue(String name) {
String result = properties.get(name); String result = properties.get(name);
if (result == null) { if (result == null) {
throw new AuthConfigException("missing config property "+name); throw new AuthConfigException("missing config property " + name);
} }
return result; return result;
} }
...@@ -65,7 +65,7 @@ public class ConfigProperties { ...@@ -65,7 +65,7 @@ public class ConfigProperties {
public int getIntValue(String name) { public int getIntValue(String name) {
String result = properties.get(name); String result = properties.get(name);
if (result == null) { if (result == null) {
throw new AuthConfigException("missing config property "+name); throw new AuthConfigException("missing config property " + name);
} }
return Integer.parseInt(result); return Integer.parseInt(result);
} }
......
...@@ -33,20 +33,21 @@ import org.h2.util.StringUtils; ...@@ -33,20 +33,21 @@ import org.h2.util.StringUtils;
* Default authenticator implementation. * Default authenticator implementation.
* <p> * <p>
* When client connectionInfo contains property AUTHREALM={realName} credentials * When client connectionInfo contains property AUTHREALM={realName} credentials
* (typically user id and password) are validated by * (typically user id and password) are validated by by
* by {@link org.h2.api.CredentialsValidator} configured for that realm. * {@link org.h2.api.CredentialsValidator} configured for that realm.
* </p> * </p>
* <p> * <p>
* When client connectionInfo doesn't contains AUTHREALM property credentials * When client connectionInfo doesn't contains AUTHREALM property credentials
* are validated internally on the database * are validated internally on the database
* </p> * </p>
* <p> * <p>
* Rights assignment can be managed through {@link org.h2.api.UserToRolesMapper} * Rights assignment can be managed through {@link org.h2.api.UserToRolesMapper}
* </p> * </p>
* <p> * <p>
* Default configuration has a realm H2 that validate credentials through JAAS api (appName=h2). * Default configuration has a realm H2 that validate credentials through JAAS
* To customize configuration set h2.authConfigFile system property to refer a valid h2auth.xml config file * api (appName=h2). To customize configuration set h2.authConfigFile system
* </p> * property to refer a valid h2auth.xml config file
* </p>
*/ */
public class DefaultAuthenticator implements Authenticator { public class DefaultAuthenticator implements Authenticator {
...@@ -69,8 +70,8 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -69,8 +70,8 @@ public class DefaultAuthenticator implements Authenticator {
private static DefaultAuthenticator instance; private static DefaultAuthenticator instance;
protected static final DefaultAuthenticator getInstance() { protected static final DefaultAuthenticator getInstance() {
if (instance==null) { if (instance == null) {
instance= new DefaultAuthenticator(); instance = new DefaultAuthenticator();
} }
return instance; return instance;
} }
...@@ -84,9 +85,9 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -84,9 +85,9 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Create authenticator and optionally skip the default configuration. This * Create authenticator and optionally skip the default configuration. This
* 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;
...@@ -94,7 +95,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -94,7 +95,7 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* If set save users externals defined during the authentication. * If set save users externals defined during the authentication.
* *
* @return * @return
*/ */
public boolean isPersistUsers() { public boolean isPersistUsers() {
...@@ -107,7 +108,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -107,7 +108,7 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* If set create external users in the database if not present. * If set create external users in the database if not present.
* *
* @return * @return
*/ */
public boolean isAllowUserRegistration() { public boolean isAllowUserRegistration() {
...@@ -119,9 +120,9 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -119,9 +120,9 @@ public class DefaultAuthenticator implements Authenticator {
} }
/** /**
* When set create roles not found in the database. If not set roles not found * When set create roles not found in the database. If not set roles not
* in the database are silently skipped * found in the database are silently skipped
* *
* @return * @return
*/ */
public boolean isCreateMissingRoles() { public boolean isCreateMissingRoles() {
...@@ -134,9 +135,11 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -134,9 +135,11 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Add an authentication realm. Realms are case insensitive * Add an authentication realm. Realms are case insensitive
* *
* @param name realm name * @param name
* @param credentialsValidator credentials validator for realm * realm name
* @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);
...@@ -144,7 +147,7 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -144,7 +147,7 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* UserToRoleMappers assign roles to authenticated users * UserToRoleMappers assign roles to authenticated users
* *
* @return current UserToRoleMappers active * @return current UserToRoleMappers active
*/ */
public List<UserToRolesMapper> getUserToRolesMappers() { public List<UserToRolesMapper> getUserToRolesMappers() {
...@@ -161,14 +164,16 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -161,14 +164,16 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Initializes the authenticator (it is called by AuthententicationManager) * Initializes the authenticator (it is called by AuthententicationManager)
* *
* this method is skipped if skipDefaultInitialization is set * this method is skipped if skipDefaultInitialization is set Order of
* Order of initialization is * initialization is
* <ol> * <ol>
* <li>Check h2.authConfigFile system property.</li> * <li>Check h2.authConfigFile system property.</li>
* <li>Use the default configuration hard coded</li> * <li>Use the default configuration hard coded</li>
* </ol> * </ol>
* @param database where authenticator is initialized *
* @param database
* where authenticator is initialized
* @throws AuthConfigException * @throws AuthConfigException
*/ */
public void init(Database database) throws AuthConfigException { public void init(Database database) throws AuthConfigException {
...@@ -182,13 +187,14 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -182,13 +187,14 @@ public class DefaultAuthenticator implements Authenticator {
if (initialized) { if (initialized) {
return; return;
} }
Trace trace=database.getTrace(Trace.DATABASE); Trace trace = database.getTrace(Trace.DATABASE);
URL h2AuthenticatorConfigurationUrl = null; URL h2AuthenticatorConfigurationUrl = null;
try { try {
String configFile = SysProperties.AUTH_CONFIG_FILE; 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);
} }
...@@ -201,11 +207,12 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -201,11 +207,12 @@ public class DefaultAuthenticator implements Authenticator {
configureFromUrl(h2AuthenticatorConfigurationUrl); configureFromUrl(h2AuthenticatorConfigurationUrl);
} }
} catch (Exception e) { } catch (Exception e) {
trace.error(e, "DefaultAuthenticator.config: an error occurred during configuration from {0} ", h2AuthenticatorConfigurationUrl); trace.error(e, "DefaultAuthenticator.config: an error occurred during configuration from {0} ",
throw new AuthConfigException("Failed to configure authentication from " + h2AuthenticatorConfigurationUrl, h2AuthenticatorConfigurationUrl);
e); throw new AuthConfigException(
"Failed to configure authentication from " + h2AuthenticatorConfigurationUrl, e);
} }
initialized=true; initialized = true;
} }
} }
...@@ -223,8 +230,9 @@ public class DefaultAuthenticator implements Authenticator { ...@@ -223,8 +230,9 @@ public class DefaultAuthenticator implements Authenticator {
/** /**
* Configure the authenticator from a configuration file * Configure the authenticator from a configuration file
* *
* @param configUrl URL of configuration file * @param configUrl
* URL of configuration file
* @throws Exception * @throws Exception
*/ */
public void configureFromUrl(URL configUrl) throws Exception { public void configureFromUrl(URL configUrl) throws Exception {
......
...@@ -31,7 +31,7 @@ public class H2AuthConfig { ...@@ -31,7 +31,7 @@ public class H2AuthConfig {
public void setAllowUserRegistration(boolean allowUserRegistration) { public void setAllowUserRegistration(boolean allowUserRegistration) {
this.allowUserRegistration = allowUserRegistration; this.allowUserRegistration = allowUserRegistration;
} }
@XmlAttribute @XmlAttribute
boolean createMissingRoles=true; boolean createMissingRoles=true;
......
...@@ -23,11 +23,12 @@ public class PropertyConfig { ...@@ -23,11 +23,12 @@ public class PropertyConfig {
public PropertyConfig() { public PropertyConfig() {
} }
public PropertyConfig(String name, String value) { public PropertyConfig(String name, String value) {
this.name=name; this.name = name;
this.value=value; this.value = value;
} }
public String getName() { public String getName() {
return name; return name;
} }
......
...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType; ...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
/**
* Configuration for authentication realm.
*/
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class RealmConfig { public class RealmConfig {
......
...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType; ...@@ -13,6 +13,9 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
/**
* Configuration for class that maps users to roles.
*/
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class UserToRolesMapperConfig { public class UserToRolesMapperConfig {
......
...@@ -15,7 +15,7 @@ import org.h2.security.auth.ConfigProperties; ...@@ -15,7 +15,7 @@ import org.h2.security.auth.ConfigProperties;
/** /**
* Assign to user a role based on realm name * Assign to user a role based on realm name
* *
* * <p> * * <p>
* Configuration parameters: * Configuration parameters:
* </p> * </p>
...@@ -30,14 +30,14 @@ public class AssignRealmNameRole implements UserToRolesMapper{ ...@@ -30,14 +30,14 @@ public class AssignRealmNameRole implements UserToRolesMapper{
public AssignRealmNameRole() { public AssignRealmNameRole() {
this("@%s"); this("@%s");
} }
public AssignRealmNameRole(String roleNameFormat) { public AssignRealmNameRole(String roleNameFormat) {
this.roleNameFormat = roleNameFormat; this.roleNameFormat = roleNameFormat;
} }
@Override @Override
public void configure(ConfigProperties configProperties) { public void configure(ConfigProperties configProperties) {
roleNameFormat=configProperties.getStringValue("roleNameFormat",roleNameFormat); roleNameFormat=configProperties.getStringValue("roleNameFormat",roleNameFormat);
} }
@Override @Override
......
...@@ -19,8 +19,8 @@ import org.h2.security.auth.AuthenticationInfo; ...@@ -19,8 +19,8 @@ import org.h2.security.auth.AuthenticationInfo;
import org.h2.security.auth.ConfigProperties; 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
* *
* <p> * <p>
* Configuration parameters: * Configuration parameters:
* </p> * </p>
...@@ -49,17 +49,17 @@ public class JaasCredentialsValidator implements CredentialsValidator { ...@@ -49,17 +49,17 @@ public class JaasCredentialsValidator implements CredentialsValidator {
@Override @Override
public void configure(ConfigProperties configProperties) { public void configure(ConfigProperties configProperties) {
appName=configProperties.getStringValue("appName",appName); appName=configProperties.getStringValue("appName",appName);
} }
class AuthenticationInfoCallbackHandler implements CallbackHandler { class AuthenticationInfoCallbackHandler implements CallbackHandler {
AuthenticationInfo authenticationInfo; AuthenticationInfo authenticationInfo;
AuthenticationInfoCallbackHandler(AuthenticationInfo authenticationInfo) { AuthenticationInfoCallbackHandler(AuthenticationInfo authenticationInfo) {
this.authenticationInfo = authenticationInfo; this.authenticationInfo = authenticationInfo;
} }
@Override @Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) { for (int i = 0; i < callbacks.length; i++) {
...@@ -70,12 +70,13 @@ public class JaasCredentialsValidator implements CredentialsValidator { ...@@ -70,12 +70,13 @@ public class JaasCredentialsValidator implements CredentialsValidator {
} }
} }
} }
} }
@Override @Override
public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception { public boolean validateCredentials(AuthenticationInfo authenticationInfo) throws Exception {
LoginContext loginContext = new LoginContext(appName,new AuthenticationInfoCallbackHandler(authenticationInfo)); LoginContext loginContext = new LoginContext(appName,
new AuthenticationInfoCallbackHandler(authenticationInfo));
loginContext.login(); loginContext.login();
authenticationInfo.setNestedIdentity(loginContext.getSubject()); authenticationInfo.setNestedIdentity(loginContext.getSubject());
return true; return true;
......
...@@ -21,7 +21,8 @@ import org.h2.security.auth.ConfigProperties; ...@@ -21,7 +21,8 @@ import org.h2.security.auth.ConfigProperties;
* Configuration parameters: * Configuration parameters:
* </p> * </p>
* <ul> * <ul>
* <li>bindDnPattern bind dn pattern with %u instead of username (example: uid=%u,ou=users,dc=example,dc=com)</li> * <li>bindDnPattern bind dn pattern with %u instead of username
* (example: uid=%u,ou=users,dc=example,dc=com)</li>
* <li>host ldap server</li> * <li>host ldap server</li>
* <li>port of ldap service; optional, by default 389 for unsecure, 636 for secure</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> * <li>secure, optional by default is true (use SSL)</li>
......
...@@ -22,19 +22,19 @@ import org.h2.security.auth.ConfigProperties; ...@@ -22,19 +22,19 @@ import org.h2.security.auth.ConfigProperties;
* <ul> * <ul>
* <li>roles role list separated by comma</li> * <li>roles role list separated by comma</li>
* </ul> * </ul>
* *
*/ */
public class StaticRolesMapper implements UserToRolesMapper { public class StaticRolesMapper implements UserToRolesMapper {
private Collection<String> roles; private Collection<String> roles;
public StaticRolesMapper() { public StaticRolesMapper() {
} }
public StaticRolesMapper(String... roles) { public StaticRolesMapper(String... roles) {
this.roles=Arrays.asList(roles); this.roles=Arrays.asList(roles);
} }
@Override @Override
public void configure(ConfigProperties configProperties) { public void configure(ConfigProperties configProperties) {
String rolesString=configProperties.getStringValue("roles", ""); String rolesString=configProperties.getStringValue("roles", "");
......
...@@ -17,7 +17,7 @@ import org.h2.util.StringUtils; ...@@ -17,7 +17,7 @@ import org.h2.util.StringUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
/** /**
* This credentials validator matches the user and password with the configured * This credentials validator matches the user and password with the configured
* Usage should be limited to test purposes * Usage should be limited to test purposes
* *
*/ */
...@@ -30,7 +30,7 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -30,7 +30,7 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
public StaticUserCredentialsValidator() { public StaticUserCredentialsValidator() {
} }
public StaticUserCredentialsValidator(String userNamePattern,String password) { public StaticUserCredentialsValidator(String userNamePattern,String password) {
if (userNamePattern!=null) { if (userNamePattern!=null) {
this.userNamePattern=Pattern.compile(userNamePattern.toUpperCase()); this.userNamePattern=Pattern.compile(userNamePattern.toUpperCase());
...@@ -38,10 +38,9 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -38,10 +38,9 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
salt=MathUtils.secureRandomBytes(256); salt=MathUtils.secureRandomBytes(256);
hashWithSalt=SHA256.getHashWithSalt(password.getBytes(), salt); hashWithSalt=SHA256.getHashWithSalt(password.getBytes(), salt);
} }
@Override @Override
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()) { if (!userNamePattern.matcher(authenticationInfo.getUserName()).matches()) {
return false; return false;
...@@ -50,7 +49,8 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -50,7 +49,8 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
if (password!=null) { if (password!=null) {
return password.equals(authenticationInfo.getPassword()); return password.equals(authenticationInfo.getPassword());
} }
return Utils.compareSecure(hashWithSalt,SHA256.getHashWithSalt(authenticationInfo.getPassword().getBytes(), salt)); return Utils.compareSecure(hashWithSalt,
SHA256.getHashWithSalt(authenticationInfo.getPassword().getBytes(), salt));
} }
@Override @Override
...@@ -66,7 +66,7 @@ public class StaticUserCredentialsValidator implements CredentialsValidator { ...@@ -66,7 +66,7 @@ public class StaticUserCredentialsValidator implements CredentialsValidator {
} }
String hashString=configProperties.getStringValue("hash", null); String hashString=configProperties.getStringValue("hash", null);
if (hashString!=null) { if (hashString!=null) {
hashWithSalt = SHA256.getHashWithSalt(StringUtils.convertHexToBytes(hashString), salt); hashWithSalt = SHA256.getHashWithSalt(StringUtils.convertHexToBytes(hashString), salt);
} }
} }
......
...@@ -510,7 +510,8 @@ public abstract class Table extends SchemaObjectBase { ...@@ -510,7 +510,8 @@ public abstract class Table extends SchemaObjectBase {
try { try {
removeRow(session, o); removeRow(session, o);
} catch (DbException e) { } catch (DbException e) {
if (e.getErrorCode() == ErrorCode.CONCURRENT_UPDATE_1 || e.getErrorCode() == ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1) { if (e.getErrorCode() == ErrorCode.CONCURRENT_UPDATE_1
|| e.getErrorCode() == ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1) {
session.rollbackTo(rollback, false); session.rollbackTo(rollback, false);
session.startStatementWithinTransaction(); session.startStatementWithinTransaction();
rollback = session.setSavepoint(); rollback = session.setSavepoint();
......
...@@ -15,7 +15,7 @@ import javax.security.auth.login.LoginException; ...@@ -15,7 +15,7 @@ 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 * Dummy login module used for test cases
*/ */
public class MyLoginModule implements LoginModule{ public class MyLoginModule implements LoginModule{
......
...@@ -31,6 +31,9 @@ import org.h2.security.auth.impl.StaticRolesMapper; ...@@ -31,6 +31,9 @@ import org.h2.security.auth.impl.StaticRolesMapper;
import org.h2.security.auth.impl.StaticUserCredentialsValidator; import org.h2.security.auth.impl.StaticUserCredentialsValidator;
import org.h2.test.TestBase; import org.h2.test.TestBase;
/**
* Test for custom authentication.
*/
public class TestAuthentication extends TestBase { public class TestAuthentication extends TestBase {
public static void main(String... a) throws Exception { public static void main(String... a) throws Exception {
...@@ -166,7 +169,7 @@ public class TestAuthentication extends TestBase { ...@@ -166,7 +169,7 @@ public class TestAuthentication extends TestBase {
} }
protected void testDatasource() throws Exception { protected void testDatasource() throws Exception {
DataSource dataSource = JdbcConnectionPool.create( DataSource dataSource = JdbcConnectionPool.create(
getDatabaseURL() + ";AUTHREALM=" + getRealmName().toUpperCase(), getExternalUser(), getDatabaseURL() + ";AUTHREALM=" + getRealmName().toUpperCase(), getExternalUser(),
getExternalUserPassword()); getExternalUserPassword());
...@@ -221,7 +224,8 @@ public class TestAuthentication extends TestBase { ...@@ -221,7 +224,8 @@ public class TestAuthentication extends TestBase {
try { try {
try { try {
Connection wrongLoginConnection = DriverManager.getConnection( Connection wrongLoginConnection = DriverManager.getConnection(
getDatabaseURL() + ";AUTHREALM=" + getRealmName().toUpperCase(), "___" + getExternalUser(), ""); getDatabaseURL() + ";AUTHREALM=" + getRealmName().toUpperCase(), "___" + getExternalUser(),
"");
wrongLoginConnection.close(); wrongLoginConnection.close();
throw new Exception( throw new Exception(
"unregistered external users should not be able to login when allowUserRegistration=false"); "unregistered external users should not be able to login when allowUserRegistration=false");
...@@ -241,7 +245,7 @@ public class TestAuthentication extends TestBase { ...@@ -241,7 +245,7 @@ public class TestAuthentication extends TestBase {
defaultAuthenticator.setAllowUserRegistration(initialValueAllow); defaultAuthenticator.setAllowUserRegistration(initialValueAllow);
} }
} }
public void testStaticUserCredentials() throws Exception { public void testStaticUserCredentials() throws Exception {
String userName="STATICUSER3"; String userName="STATICUSER3";
Connection rightConnection = DriverManager.getConnection( Connection rightConnection = DriverManager.getConnection(
...@@ -254,7 +258,7 @@ public class TestAuthentication extends TestBase { ...@@ -254,7 +258,7 @@ public class TestAuthentication extends TestBase {
rightConnection.close(); rightConnection.close();
} }
} }
protected void testSet() throws Exception{ protected void testSet() throws Exception{
Connection rightConnection = DriverManager.getConnection( Connection rightConnection = DriverManager.getConnection(
getDatabaseURL()+";AUTHENTICATOR=FALSE","DBA",""); getDatabaseURL()+";AUTHENTICATOR=FALSE","DBA","");
......
...@@ -66,7 +66,6 @@ public class TestMvcc4 extends TestBase { ...@@ -66,7 +66,6 @@ public class TestMvcc4 extends TestBase {
c1.setAutoCommit(false); c1.setAutoCommit(false);
//Fire off a concurrent update. //Fire off a concurrent update.
final Thread mainThread = Thread.currentThread();
final CountDownLatch executedUpdate = new CountDownLatch(1); final CountDownLatch executedUpdate = new CountDownLatch(1);
new Thread() { new Thread() {
@Override @Override
...@@ -83,7 +82,8 @@ public class TestMvcc4 extends TestBase { ...@@ -83,7 +82,8 @@ public class TestMvcc4 extends TestBase {
executedUpdate.countDown(); executedUpdate.countDown();
// interrogate new "blocker_id" metatable field instead of // interrogate new "blocker_id" metatable field instead of
// relying on stacktraces!? to determine when session is blocking // relying on stacktraces!? to determine when session is blocking
PreparedStatement stmt = c2.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.SESSIONS WHERE BLOCKER_ID = SESSION_ID()"); PreparedStatement stmt = c2.prepareStatement(
"SELECT * FROM INFORMATION_SCHEMA.SESSIONS WHERE BLOCKER_ID = SESSION_ID()");
ResultSet resultSet; ResultSet resultSet;
do { do {
resultSet = stmt.executeQuery(); resultSet = stmt.executeQuery();
......
...@@ -299,7 +299,8 @@ public class TestScript extends TestBase { ...@@ -299,7 +299,8 @@ public class TestScript extends TestBase {
private void process(String sql, boolean allowReconnect) throws Exception { private void process(String sql, boolean allowReconnect) throws Exception {
if (allowReconnect && reconnectOften) { if (allowReconnect && reconnectOften) {
if (!containsTempTables() && ((JdbcConnection) conn).isRegularMode() && conn.getSchema().equals("PUBLIC")) { if (!containsTempTables() && ((JdbcConnection) conn).isRegularMode()
&& conn.getSchema().equals("PUBLIC")) {
boolean autocommit = conn.getAutoCommit(); boolean autocommit = conn.getAutoCommit();
if (autocommit && random.nextInt(10) < 1) { if (autocommit && random.nextInt(10) < 1) {
// reconnect 10% of the time // reconnect 10% of the time
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论