Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
78b5a2dc
Unverified
提交
78b5a2dc
authored
6 年前
作者:
Alessandro Ventura
提交者:
GitHub
6 年前
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
External authentication
Added support for custom authentication at database level
上级
2bb8ab6a
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
31 个修改的文件
包含
1837 行增加
和
8 行删除
+1837
-8
features.html
h2/src/docsrc/html/features.html
+76
-0
Authenticator.java
h2/src/main/org/h2/api/Authenticator.java
+37
-0
CredentialsValidator.java
h2/src/main/org/h2/api/CredentialsValidator.java
+26
-0
UserToRolesMapper.java
h2/src/main/org/h2/api/UserToRolesMapper.java
+29
-0
Set.java
h2/src/main/org/h2/command/dml/Set.java
+18
-0
SetTypes.java
h2/src/main/org/h2/command/dml/SetTypes.java
+7
-1
ConnectionInfo.java
h2/src/main/org/h2/engine/ConnectionInfo.java
+13
-2
Database.java
h2/src/main/org/h2/engine/Database.java
+43
-0
Engine.java
h2/src/main/org/h2/engine/Engine.java
+10
-5
InternalAuthenticator.java
h2/src/main/org/h2/engine/InternalAuthenticator.java
+35
-0
RightOwner.java
h2/src/main/org/h2/engine/RightOwner.java
+23
-0
UserBuilder.java
h2/src/main/org/h2/engine/UserBuilder.java
+23
-0
AuthConfigException.java
h2/src/main/org/h2/security/auth/AuthConfigException.java
+29
-0
AuthenticationException.java
...rc/main/org/h2/security/auth/AuthenticationException.java
+29
-0
AuthenticationInfo.java
h2/src/main/org/h2/security/auth/AuthenticationInfo.java
+82
-0
AuthenticatorBuilder.java
h2/src/main/org/h2/security/auth/AuthenticatorBuilder.java
+40
-0
ConfigProperties.java
h2/src/main/org/h2/security/auth/ConfigProperties.java
+86
-0
Configurable.java
h2/src/main/org/h2/security/auth/Configurable.java
+17
-0
DefaultAuthenticator.java
h2/src/main/org/h2/security/auth/DefaultAuthenticator.java
+334
-0
H2AuthConfig.java
h2/src/main/org/h2/security/auth/H2AuthConfig.java
+73
-0
PropertyConfig.java
h2/src/main/org/h2/security/auth/PropertyConfig.java
+46
-0
RealmConfig.java
h2/src/main/org/h2/security/auth/RealmConfig.java
+51
-0
UserToRolesMapperConfig.java
...rc/main/org/h2/security/auth/UserToRolesMapperConfig.java
+40
-0
AssignRealmNameRole.java
...c/main/org/h2/security/auth/impl/AssignRealmNameRole.java
+38
-0
JaasCredentialsValidator.java
...n/org/h2/security/auth/impl/JaasCredentialsValidator.java
+80
-0
LdapCredentialsValidator.java
...n/org/h2/security/auth/impl/LdapCredentialsValidator.java
+69
-0
StaticRolesMapper.java
h2/src/main/org/h2/security/auth/impl/StaticRolesMapper.java
+47
-0
StaticUserCredentialsValidator.java
...h2/security/auth/impl/StaticUserCredentialsValidator.java
+73
-0
MyLoginModule.java
h2/src/test/org/h2/test/auth/MyLoginModule.java
+58
-0
TestAuthentication.java
h2/src/test/org/h2/test/auth/TestAuthentication.java
+237
-0
TestAuthenticationDefaults.java
h2/src/test/org/h2/test/auth/TestAuthenticationDefaults.java
+68
-0
没有找到文件。
h2/src/docsrc/html/features.html
浏览文件 @
78b5a2dc
...
...
@@ -83,6 +83,8 @@ Features
Compacting a Database
</a><br
/>
<a
href=
"#cache_settings"
>
Cache Settings
</a><br
/>
<a
href=
"#external_authentication"
>
External Authentication
</a><br
/>
<h2
id=
"feature_list"
>
Feature List
</h2>
<h3>
Main Features
</h3>
...
...
@@ -1826,6 +1828,80 @@ To get information about page reads and writes, and the current caching algorith
call
<code>
SELECT * FROM INFORMATION_SCHEMA.SETTINGS
</code>
. The number of pages read / written
is listed.
</p>
<h2
id=
"external_authentication"
>
External authentication
</h2>
<p>
External authentication allows to optionally validate user credentials externally (JAAS,LDAP,custom classes).
Is also possible to temporary assign roles to to externally authenticated users
</p>
<p>
Master user cannot be externally authenticated
</p>
<p>
To enable external authentication on a database execute statement
<code>
SET AUTHENTICATOR='on'
</code>
. This setting in persisted on the database.
</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>
is the identifier of the authentication realm (see later).
</p>
<p>
External authentication requires to send password to the server. For this reason is works only on local connection or remote over ssl
</p>
<p>
By default external authentication is performed trough JAAS login interface (configuration name is
<code>
h2
</code>
).
To configure JAAS add argument
<code>
-Djava.security.auth.login.config=jaas.conf
</code>
Here an example of
<a
href=
"https://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html"
>
JAAS login configuration file
</a>
content:
</p>
<pre>
h2 {
com.sun.security.auth.module.LdapLoginModule REQUIRED \
userProvider="ldap://127.0.0.1:10389" authIdentity="uid={USERNAME},ou=people,dc=example,dc=com" \
debug=true useSSL=false ;
};
</pre>
<p>
Is it possible to specify custom authentication settings by putting
<code>
h2auth.xml
</code>
file in the classpath or by using
JVM argument
<code>
-Dh2auth.configurationFile={urlOfH2Auth.xml}
</code>
. Here an example of h2auth.xml file content:
</p>
<pre>
<
h2Auth allowUserRegistration="false" createMissingRoles="true"
>
<
!-- realm: DUMMY authenticate users named DUMMY[0-9] with a static password --
>
<
realm name="DUMMY"
validatorClass="org.h2.security.auth.impl.FixedPasswordCredentialsValidator"
>
<
property name="userNamePattern" value="DUMMY[0-9]" /
>
<
property name="password" value="mock" /
>
<
/realm
>
<
!-- realm LDAPEXAMPLE:perform credentials validation on LDAP --
>
<
realm name="LDAPEXAMPLE"
validatorClass="org.h2.security.auth.impl.LdapCredentialsValidator"
>
<
property name="bindDnPattern" value="uid=%u,ou=people,dc=example,dc=com" /
>
<
property name="host" value="127.0.0.1" /
>
<
property name="port" value="10389" /
>
<
property name="secure" value="false" /
>
<
/realm
>
<
!-- realm JAAS: perform credentials validation by using JAAS api --
>
<
realm name="JAAS"
validatorClass="org.h2.security.auth.impl.JaasCredentialsValidator"
>
<
property name="appName" value="H2" /
>
<
/realm
>
<
!--Assign to each user role @{REALM} --
>
<
userToRolesMapper class="org.h2.security.auth.impl.AssignRealmNameRole"/
>
<
!--Assign to each user role REMOTEUSER --
>
<
userToRolesMapper class="org.h2.security.auth.impl.StaticRolesMapper"
>
<
property name="roles" value="REMOTEUSER"/
>
<
/userToRolesMapper
>
<
/h2Auth
>
</pre>
<p>
Custom credentials validators must implement the interface
<code>
org.h2.api.CredentialsValidator
</code>
</p>
<p>
Custom criteria for role assignments must implement the interface
<code>
org.h2.api.UserToRoleMapper
</code>
</p>
<!-- [close] { -->
</div></td></tr></table>
<!-- } --><!-- analytics -->
</body></html>
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/api/Authenticator.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
.
api
;
import
org.h2.engine.Database
;
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
*/
public
interface
Authenticator
{
/**
* perform user authentication
*
* @param authenticationInfo
* @param database
* @return valid database user or null if user doesn't exists in the 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
* when the authenticator is set.
* @param database = target database
* @throws AuthConfigException
*/
void
init
(
Database
database
)
throws
AuthConfigException
;
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/api/CredentialsValidator.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
.
api
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.Configurable
;
/**
* A class that implement this interface can be used to validate
* credentials provided by client.
* It is users by DefaultAuthenticator
*/
public
interface
CredentialsValidator
extends
Configurable
{
/**
* Validate user credential
* @param authenticationInfo = authentication info
* @return true if credentials are valid, otherwise false
* @throws Exception = any exception occurred (invalid credentials or internal issue) prevent user login
*/
boolean
validateCredentials
(
AuthenticationInfo
authenticationInfo
)
throws
Exception
;
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/api/UserToRolesMapper.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
.
api
;
import
java.util.Collection
;
import
java.util.Set
;
import
org.h2.security.auth.AuthenticationException
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.Configurable
;
/**
* A class that implement this interface can be used during
* authentication to map external users to database roles.
* It is used by DefaultAuthenticator
*/
public
interface
UserToRolesMapper
extends
Configurable
{
/**
* Map user identified by authentication info to a set of granted roles
* @param authenticationInfo
* @return list of roles to be assigned to the user temporary
* @throws AuthenticationException
*/
Collection
<
String
>
mapUserToRoles
(
AuthenticationInfo
authenticationInfo
)
throws
AuthenticationException
;
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Set.java
浏览文件 @
78b5a2dc
...
...
@@ -18,9 +18,11 @@ import org.h2.engine.Setting;
import
org.h2.expression.Expression
;
import
org.h2.expression.ValueExpression
;
import
org.h2.message.DbException
;
import
org.h2.message.Trace
;
import
org.h2.result.ResultInterface
;
import
org.h2.result.RowFactory
;
import
org.h2.schema.Schema
;
import
org.h2.security.auth.AuthenticatorBuilder
;
import
org.h2.table.Table
;
import
org.h2.tools.CompressTool
;
import
org.h2.util.JdbcUtils
;
...
...
@@ -540,6 +542,22 @@ public class Set extends Prepared {
session
.
getColumnNamerConfiguration
().
configure
(
expression
.
getColumnName
());
break
;
}
case
SetTypes
.
AUTHENTICATOR
:
{
session
.
getUser
().
checkAdmin
();
String
authenticatorString
=
expression
.
getValue
(
session
).
getString
();
try
{
database
.
setAuthenticator
(
AuthenticatorBuilder
.
buildAuthenticator
(
authenticatorString
));
addOrUpdateSetting
(
name
,
"'"
+
authenticatorString
+
"'"
,
0
);
}
catch
(
Exception
e
)
{
//Errors during start are ignored to allow to open the database
if
(
database
.
isStarting
())
{
database
.
getTrace
(
Trace
.
DATABASE
).
error
(
e
,
"SET AUTHENTICATOR: failed to set authenticator {0} during database start"
,
authenticatorString
);
}
else
{
throw
DbException
.
convert
(
e
);
}
}
break
;
}
default
:
DbException
.
throwInternalError
(
"type="
+
type
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/SetTypes.java
浏览文件 @
78b5a2dc
...
...
@@ -252,7 +252,12 @@ public class SetTypes {
*/
public
static
final
int
COLUMN_NAME_RULES
=
48
;
private
static
final
int
COUNT
=
COLUMN_NAME_RULES
+
1
;
/**
* The type of a SET AUTHENTICATOR statement.
*/
public
static
final
int
AUTHENTICATOR
=
49
;
private
static
final
int
COUNT
=
AUTHENTICATOR
+
1
;
private
static
final
ArrayList
<
String
>
TYPES
;
...
...
@@ -311,6 +316,7 @@ public class SetTypes {
list
.
add
(
LAZY_QUERY_EXECUTION
,
"LAZY_QUERY_EXECUTION"
);
list
.
add
(
BUILTIN_ALIAS_OVERRIDE
,
"BUILTIN_ALIAS_OVERRIDE"
);
list
.
add
(
COLUMN_NAME_RULES
,
"COLUMN_NAME_RULES"
);
list
.
add
(
AUTHENTICATOR
,
"AUTHENTICATOR"
);
TYPES
=
list
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/ConnectionInfo.java
浏览文件 @
78b5a2dc
...
...
@@ -74,9 +74,9 @@ public class ConnectionInfo implements Cloneable {
readProperties
(
info
);
readSettingsFromURL
();
setUserName
(
removeProperty
(
"USER"
,
""
));
convertPasswords
();
name
=
url
.
substring
(
Constants
.
START_URL
.
length
());
parseName
();
convertPasswords
();
String
recoverTest
=
removeProperty
(
"RECOVER_TEST"
,
null
);
if
(
recoverTest
!=
null
)
{
FilePathRec
.
register
();
...
...
@@ -95,7 +95,7 @@ public class ConnectionInfo implements Cloneable {
"IFEXISTS"
,
"INIT"
,
"PASSWORD"
,
"RECOVER"
,
"RECOVER_TEST"
,
"USER"
,
"AUTO_SERVER"
,
"AUTO_SERVER_PORT"
,
"NO_UPGRADE"
,
"AUTO_RECONNECT"
,
"OPEN_NEW"
,
"PAGE_SIZE"
,
"PASSWORD_HASH"
,
"JMX"
,
"SCOPE_GENERATED_KEYS"
};
"SCOPE_GENERATED_KEYS"
,
"AUTHREALM"
,
"_PASSWORD"
};
HashSet
<
String
>
set
=
new
HashSet
<>(
128
);
set
.
addAll
(
SetTypes
.
getTypes
());
for
(
String
key
:
connectionTime
)
{
...
...
@@ -274,8 +274,15 @@ public class ConnectionInfo implements Cloneable {
}
}
private
void
preservePasswordForAuthentication
(
Object
password
)
{
if
((
isRemote
()
==
false
||
isSSL
())
&&
prop
.
containsKey
(
"AUTHREALM"
)
&&
password
!=
null
)
{
prop
.
put
(
"_PASSWORD"
,
password
);
}
}
private
char
[]
removePassword
()
{
Object
p
=
prop
.
remove
(
"PASSWORD"
);
preservePasswordForAuthentication
(
p
);
if
(
p
==
null
)
{
return
new
char
[
0
];
}
else
if
(
p
instanceof
char
[])
{
...
...
@@ -657,4 +664,8 @@ public class ConnectionInfo implements Cloneable {
return
url
;
}
public
void
cleanAuthenticationInfo
()
{
removeProperty
(
"AUTHREALM"
,
false
);
removeProperty
(
"_PASSWORD"
,
false
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/Database.java
浏览文件 @
78b5a2dc
...
...
@@ -20,6 +20,7 @@ import java.util.concurrent.ConcurrentHashMap;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.atomic.AtomicLong
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.h2.api.Authenticator
;
import
org.h2.api.DatabaseEventListener
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.JavaObjectSerializer
;
...
...
@@ -43,6 +44,7 @@ import org.h2.schema.Schema;
import
org.h2.schema.SchemaObject
;
import
org.h2.schema.Sequence
;
import
org.h2.schema.TriggerObject
;
import
org.h2.security.auth.AuthenticatorBuilder
;
import
org.h2.store.DataHandler
;
import
org.h2.store.FileLock
;
import
org.h2.store.FileLockMethod
;
...
...
@@ -207,6 +209,9 @@ public class Database implements DataHandler {
private
QueryStatisticsData
queryStatisticsData
;
private
RowFactory
rowFactory
=
RowFactory
.
DEFAULT
;
private
Authenticator
authenticator
;
private
boolean
authenticatorInitialized
;
public
Database
(
ConnectionInfo
ci
,
String
cipher
)
{
META_LOCK_DEBUGGING
.
set
(
null
);
META_LOCK_DEBUGGING_DB
.
set
(
null
);
...
...
@@ -2947,4 +2952,42 @@ public class Database implements DataHandler {
return
engine
;
}
private
void
initAuthenticator
()
{
if
(
authenticatorInitialized
)
{
return
;
}
try
{
String
authenticatorString
=
null
;
Setting
authenticatorSetting
=
findSetting
(
"AUTHENTICATOR"
);
if
(
authenticatorSetting
!=
null
)
{
authenticatorString
=
authenticatorSetting
.
getStringValue
();
}
Authenticator
authenticator
=
AuthenticatorBuilder
.
buildAuthenticator
(
authenticatorString
);
setAuthenticator
(
authenticator
);
}
catch
(
Exception
e
)
{
throw
DbException
.
convert
(
e
);
}
}
/**
* get authenticator for database users
* @return authenticator set for database
*/
public
Authenticator
getAuthenticator
()
{
initAuthenticator
();
return
authenticator
==
null
?
InternalAuthenticator
.
INSTANCE
:
authenticator
;
}
/**
* Set current database authenticator
*
* @param authenticator = authenticator to set, null to revert to the Internal authenticator
*/
public
void
setAuthenticator
(
Authenticator
authenticator
)
{
if
(
authenticator
!=
null
)
{
authenticator
.
init
(
this
);
};
this
.
authenticator
=
authenticator
;
authenticatorInitialized
=
true
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/Engine.java
浏览文件 @
78b5a2dc
...
...
@@ -14,6 +14,8 @@ import org.h2.command.Parser;
import
org.h2.command.dml.SetTypes
;
import
org.h2.message.DbException
;
import
org.h2.message.Trace
;
import
org.h2.security.auth.AuthenticationException
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.store.FileLock
;
import
org.h2.store.FileLockMethod
;
import
org.h2.util.MathUtils
;
...
...
@@ -53,6 +55,7 @@ public class Engine implements SessionFactory {
boolean
openNew
=
ci
.
getProperty
(
"OPEN_NEW"
,
false
);
boolean
opened
=
false
;
User
user
=
null
;
AuthenticationInfo
authenticationInfo
=
new
AuthenticationInfo
(
ci
);
synchronized
(
DATABASES
)
{
if
(
openNew
||
ci
.
isUnnamedInMemory
())
{
database
=
null
;
...
...
@@ -90,11 +93,12 @@ public class Engine implements SessionFactory {
}
if
(
user
==
null
)
{
if
(
database
.
validateFilePasswordHash
(
cipher
,
ci
.
getFilePasswordHash
()))
{
user
=
database
.
findUser
(
ci
.
getUserName
());
if
(
user
!=
null
)
{
if
(!
user
.
validateUserPasswordHash
(
ci
.
getUserPasswordHash
()))
{
user
=
null
;
}
try
{
user
=
database
.
getAuthenticator
().
authenticate
(
authenticationInfo
,
database
);
}
catch
(
AuthenticationException
authenticationError
)
{
database
.
getTrace
(
Trace
.
DATABASE
).
error
(
authenticationError
,
"an error occurred during authentication; user: \""
+
ci
.
getUserName
()
+
"\""
,
ci
.
getUserName
());
}
}
if
(
opened
&&
(
user
==
null
||
!
user
.
isAdmin
()))
{
...
...
@@ -103,6 +107,7 @@ public class Engine implements SessionFactory {
database
.
setEventListener
(
null
);
}
}
ci
.
cleanAuthenticationInfo
();
if
(
user
==
null
)
{
DbException
er
=
DbException
.
get
(
ErrorCode
.
WRONG_USER_OR_PASSWORD
);
database
.
getTrace
(
Trace
.
DATABASE
).
error
(
er
,
"wrong user or password; user: \""
+
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/InternalAuthenticator.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
{
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/RightOwner.java
浏览文件 @
78b5a2dc
...
...
@@ -5,7 +5,10 @@
*/
package
org
.
h2
.
engine
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map.Entry
;
import
org.h2.table.Table
;
...
...
@@ -150,6 +153,26 @@ public abstract class RightOwner extends DbObjectBase {
grantedRoles
=
null
;
}
}
/**
* Remove all the temporary rights granted on roles
*/
public
void
revokeTemporaryRightsOnRoles
()
{
if
(
grantedRoles
==
null
)
{
return
;
}
List
<
Role
>
rolesToRemove
=
new
ArrayList
<>();
for
(
Entry
<
Role
,
Right
>
currentEntry
:
grantedRoles
.
entrySet
())
{
if
(
currentEntry
.
getValue
().
isTemporary
()
||
currentEntry
.
getValue
().
isValid
()==
false
)
{
rolesToRemove
.
add
(
currentEntry
.
getKey
());
}
}
for
(
Role
currentRoleToRemove
:
rolesToRemove
)
{
revokeRole
(
currentRoleToRemove
);
}
}
/**
* Get the 'grant schema' right of this object.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/UserBuilder.java
0 → 100644
浏览文件 @
78b5a2dc
package
org
.
h2
.
engine
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.util.MathUtils
;
public
class
UserBuilder
{
/**
* build the database user starting from authentication informations
* @param authenticationInfo = authentication info
* @param database = target database
* @param persistent = true if the user will be persisted in the database
* @return user bean
*/
public
static
User
buildUser
(
AuthenticationInfo
authenticationInfo
,
Database
database
,
boolean
persistent
)
{
User
user
=
new
User
(
database
,
persistent
?
database
.
allocateObjectId
()
:
-
1
,
authenticationInfo
.
getFullyQualifiedName
(),
false
);
//In case of external authentication fill the password hash with random data
user
.
setUserPasswordHash
(
authenticationInfo
.
getRealm
()==
null
?
authenticationInfo
.
getConnectionInfo
().
getUserPasswordHash
():
MathUtils
.
secureRandomBytes
(
64
));
user
.
setTemporary
(
persistent
==
false
);
return
user
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/AuthConfigException.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
;
/**
* Exception thrown when an issue occurs during the authentication configuration
*
*/
public
class
AuthConfigException
extends
RuntimeException
{
public
AuthConfigException
()
{
super
();
}
public
AuthConfigException
(
String
message
)
{
super
(
message
);
}
public
AuthConfigException
(
Throwable
cause
)
{
super
(
cause
);
}
public
AuthConfigException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/AuthenticationException.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
;
/**
* Exception thrown in case of errors during authentication
*/
public
class
AuthenticationException
extends
Exception
{
public
AuthenticationException
()
{
super
();
}
public
AuthenticationException
(
String
message
)
{
super
(
message
);
}
public
AuthenticationException
(
Throwable
cause
)
{
super
(
cause
);
}
public
AuthenticationException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/AuthenticationInfo.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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.engine.ConnectionInfo
;
import
org.h2.util.StringUtils
;
/**
* Input data for authenticators; it wraps ConnectionInfo
*/
public
class
AuthenticationInfo
{
ConnectionInfo
connectionInfo
;
String
password
;
String
realm
;
/*
* Can be used by authenticator to hold informations
*/
Object
nestedIdentity
;
public
AuthenticationInfo
(
ConnectionInfo
connectionInfo
)
{
this
.
connectionInfo
=
connectionInfo
;
this
.
realm
=
connectionInfo
.
getProperty
(
"AUTHREALM"
,
null
);
if
(
this
.
realm
!=
null
)
{
this
.
realm
=
StringUtils
.
toUpperEnglish
(
this
.
realm
);
}
this
.
password
=
connectionInfo
.
getProperty
(
"_PASSWORD"
,
null
);
}
public
String
getUserName
()
{
return
connectionInfo
.
getUserName
();
}
public
String
getRealm
()
{
return
realm
;
}
public
String
getPassword
()
{
return
password
;
}
public
ConnectionInfo
getConnectionInfo
()
{
return
connectionInfo
;
}
public
String
getFullyQualifiedName
()
{
if
(
realm
==
null
)
{
return
connectionInfo
.
getUserName
();
}
else
{
return
connectionInfo
.
getUserName
()+
"@"
+
realm
;
}
}
/**
* get nested identity
* @return
*/
public
Object
getNestedIdentity
()
{
return
nestedIdentity
;
}
/**
* Method used by authenticators to hold informations about authenticated user
* @param nestedIdentity = nested identity object
*/
public
void
setNestedIdentity
(
Object
nestedIdentity
)
{
this
.
nestedIdentity
=
nestedIdentity
;
}
public
void
clean
()
{
this
.
password
=
null
;
this
.
nestedIdentity
=
null
;
connectionInfo
.
cleanAuthenticationInfo
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/AuthenticatorBuilder.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
();
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/ConfigProperties.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* wrapper for configuration properties
*/
public
class
ConfigProperties
{
Map
<
String
,
String
>
properties
;
public
ConfigProperties
()
{
properties
=
new
HashMap
<>();
}
public
ConfigProperties
(
PropertyConfig
...
configProperties
)
{
this
(
configProperties
==
null
?
null
:
Arrays
.
asList
(
configProperties
));
}
public
ConfigProperties
(
Collection
<
PropertyConfig
>
configProperties
)
{
properties
=
new
HashMap
<>();
if
(
properties
!=
null
)
{
for
(
PropertyConfig
currentProperty
:
configProperties
)
{
if
(
properties
.
put
(
currentProperty
.
getName
(),
currentProperty
.
getValue
())!=
null
)
{
throw
new
AuthConfigException
(
"duplicate property "
+
currentProperty
.
getName
());
}
}
}
}
public
String
getStringValue
(
String
name
,
String
defaultValue
)
{
String
result
=
properties
.
get
(
name
);
if
(
result
==
null
)
{
return
defaultValue
;
}
return
result
;
}
public
String
getStringValue
(
String
name
)
{
String
result
=
properties
.
get
(
name
);
if
(
result
==
null
)
{
throw
new
AuthConfigException
(
"missing config property "
+
name
);
}
return
result
;
}
public
int
getIntValue
(
String
name
,
int
defaultValue
)
{
String
result
=
properties
.
get
(
name
);
if
(
result
==
null
)
{
return
defaultValue
;
}
return
Integer
.
parseInt
(
result
);
}
public
int
getIntValue
(
String
name
)
{
String
result
=
properties
.
get
(
name
);
if
(
result
==
null
)
{
throw
new
AuthConfigException
(
"missing config property "
+
name
);
}
return
Integer
.
parseInt
(
result
);
}
public
boolean
getBooleanValue
(
String
name
,
boolean
defaultValue
)
{
String
result
=
properties
.
get
(
name
);
if
(
result
==
null
)
{
return
defaultValue
;
}
switch
(
result
)
{
case
"true"
:
case
"yes"
:
case
"1"
:
return
true
;
default
:
return
false
;
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/Configurable.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
;
/**
* describe how to perform objects runtime configuration
*/
public
interface
Configurable
{
/**
* configure the component
* @param configProperties = configuration properties
*/
void
configure
(
ConfigProperties
configProperties
);
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/DefaultAuthenticator.java
0 → 100644
浏览文件 @
78b5a2dc
差异被折叠。
点击展开。
h2/src/main/org/h2/security/auth/H2AuthConfig.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
java.util.ArrayList
;
import
java.util.List
;
import
javax.xml.bind.annotation.XmlAccessType
;
import
javax.xml.bind.annotation.XmlAccessorType
;
import
javax.xml.bind.annotation.XmlAttribute
;
import
javax.xml.bind.annotation.XmlElement
;
import
javax.xml.bind.annotation.XmlRootElement
;
/**
* Describe configuration of H2 DefaultAuthenticator
*/
@XmlRootElement
(
name
=
"h2Auth"
)
@XmlAccessorType
(
XmlAccessType
.
FIELD
)
public
class
H2AuthConfig
{
@XmlAttribute
boolean
allowUserRegistration
=
true
;
public
boolean
isAllowUserRegistration
()
{
return
allowUserRegistration
;
}
public
void
setAllowUserRegistration
(
boolean
allowUserRegistration
)
{
this
.
allowUserRegistration
=
allowUserRegistration
;
}
@XmlAttribute
boolean
createMissingRoles
=
true
;
public
boolean
isCreateMissingRoles
()
{
return
createMissingRoles
;
}
public
void
setCreateMissingRoles
(
boolean
createMissingRoles
)
{
this
.
createMissingRoles
=
createMissingRoles
;
}
@XmlElement
(
name
=
"realm"
)
List
<
RealmConfig
>
realms
;
public
List
<
RealmConfig
>
getRealms
()
{
if
(
realms
==
null
)
{
realms
=
new
ArrayList
<>();
}
return
realms
;
}
public
void
setRealms
(
List
<
RealmConfig
>
realms
)
{
this
.
realms
=
realms
;
}
@XmlElement
(
name
=
"userToRolesMapper"
)
List
<
UserToRolesMapperConfig
>
userToRolesMappers
;
public
List
<
UserToRolesMapperConfig
>
getUserToRolesMappers
()
{
if
(
userToRolesMappers
==
null
)
{
userToRolesMappers
=
new
ArrayList
<>();
}
return
userToRolesMappers
;
}
public
void
setUserToRolesMappers
(
List
<
UserToRolesMapperConfig
>
userToRolesMappers
)
{
this
.
userToRolesMappers
=
userToRolesMappers
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/PropertyConfig.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
javax.xml.bind.annotation.XmlAccessType
;
import
javax.xml.bind.annotation.XmlAccessorType
;
import
javax.xml.bind.annotation.XmlAttribute
;
/**
* Configuration property
*/
@XmlAccessorType
(
XmlAccessType
.
FIELD
)
public
class
PropertyConfig
{
@XmlAttribute
(
required
=
true
)
String
name
;
@XmlAttribute
String
value
;
public
PropertyConfig
()
{
}
public
PropertyConfig
(
String
name
,
String
value
)
{
this
.
name
=
name
;
this
.
value
=
value
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getValue
()
{
return
value
;
}
public
void
setValue
(
String
value
)
{
this
.
value
=
value
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/RealmConfig.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
java.util.ArrayList
;
import
java.util.List
;
import
javax.xml.bind.annotation.XmlAccessType
;
import
javax.xml.bind.annotation.XmlAccessorType
;
import
javax.xml.bind.annotation.XmlAttribute
;
import
javax.xml.bind.annotation.XmlElement
;
@XmlAccessorType
(
XmlAccessType
.
FIELD
)
public
class
RealmConfig
{
@XmlAttribute
(
required
=
true
)
String
name
;
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
@XmlAttribute
(
required
=
true
)
String
validatorClass
;
public
String
getValidatorClass
()
{
return
validatorClass
;
}
public
void
setValidatorClass
(
String
validatorClass
)
{
this
.
validatorClass
=
validatorClass
;
}
@XmlElement
(
name
=
"property"
)
List
<
PropertyConfig
>
properties
;
public
List
<
PropertyConfig
>
getProperties
()
{
if
(
properties
==
null
)
{
properties
=
new
ArrayList
<>();
}
return
properties
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/UserToRolesMapperConfig.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
java.util.ArrayList
;
import
java.util.List
;
import
javax.xml.bind.annotation.XmlAccessType
;
import
javax.xml.bind.annotation.XmlAccessorType
;
import
javax.xml.bind.annotation.XmlAttribute
;
import
javax.xml.bind.annotation.XmlElement
;
@XmlAccessorType
(
XmlAccessType
.
FIELD
)
public
class
UserToRolesMapperConfig
{
@XmlAttribute
(
required
=
true
,
name
=
"class"
)
String
className
;
@XmlElement
(
name
=
"property"
)
List
<
PropertyConfig
>
properties
;
public
String
getClassName
()
{
return
className
;
}
public
void
setClassName
(
String
className
)
{
this
.
className
=
className
;
}
public
List
<
PropertyConfig
>
getProperties
()
{
if
(
properties
==
null
)
{
properties
=
new
ArrayList
<>();
}
return
properties
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/impl/AssignRealmNameRole.java
0 → 100644
浏览文件 @
78b5a2dc
package
org
.
h2
.
security
.
auth
.
impl
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
org.h2.api.UserToRolesMapper
;
import
org.h2.security.auth.AuthenticationException
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.ConfigProperties
;
/**
* Assign to user a role based on realm name
*
* by default role name is @{realm}
*/
public
class
AssignRealmNameRole
implements
UserToRolesMapper
{
String
roleNameFormat
;
public
AssignRealmNameRole
()
{
this
(
"@%s"
);
}
public
AssignRealmNameRole
(
String
roleNameFormat
)
{
this
.
roleNameFormat
=
roleNameFormat
;
}
@Override
public
void
configure
(
ConfigProperties
configProperties
)
{
roleNameFormat
=
configProperties
.
getStringValue
(
"roleNameFormat"
,
roleNameFormat
);
}
@Override
public
Collection
<
String
>
mapUserToRoles
(
AuthenticationInfo
authenticationInfo
)
throws
AuthenticationException
{
return
Arrays
.
asList
(
String
.
format
(
roleNameFormat
,
authenticationInfo
.
getRealm
()));
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/impl/JaasCredentialsValidator.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
.
impl
;
import
java.io.IOException
;
import
javax.security.auth.callback.Callback
;
import
javax.security.auth.callback.CallbackHandler
;
import
javax.security.auth.callback.NameCallback
;
import
javax.security.auth.callback.PasswordCallback
;
import
javax.security.auth.callback.UnsupportedCallbackException
;
import
javax.security.auth.login.LoginContext
;
import
org.h2.api.CredentialsValidator
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.ConfigProperties
;
/**
* Validate credentials by using standard Java Authentication and Authorization Service
*
* configuration parameters:
* appName = application name inside the JAAS configuration (by default h2)
*
*/
public
class
JaasCredentialsValidator
implements
CredentialsValidator
{
public
static
final
String
DEFAULT_APPNAME
=
"h2"
;
String
appName
;
public
JaasCredentialsValidator
()
{
this
(
DEFAULT_APPNAME
);
}
/**
* Create the validator with the given name of JAAS configuration
* @param appName = name of JAAS configuration
*/
public
JaasCredentialsValidator
(
String
appName
)
{
this
.
appName
=
appName
;
}
@Override
public
void
configure
(
ConfigProperties
configProperties
)
{
appName
=
configProperties
.
getStringValue
(
"appName"
,
appName
);
}
class
AuthenticationInfoCallbackHandler
implements
CallbackHandler
{
AuthenticationInfo
authenticationInfo
;
AuthenticationInfoCallbackHandler
(
AuthenticationInfo
authenticationInfo
)
{
this
.
authenticationInfo
=
authenticationInfo
;
}
@Override
public
void
handle
(
Callback
[]
callbacks
)
throws
IOException
,
UnsupportedCallbackException
{
for
(
int
i
=
0
;
i
<
callbacks
.
length
;
i
++)
{
if
(
callbacks
[
i
]
instanceof
NameCallback
)
{
((
NameCallback
)
callbacks
[
i
]).
setName
(
authenticationInfo
.
getUserName
());
}
else
if
(
callbacks
[
i
]
instanceof
PasswordCallback
)
{
((
PasswordCallback
)
callbacks
[
i
]).
setPassword
(
authenticationInfo
.
getPassword
().
toCharArray
());
}
}
}
}
@Override
public
boolean
validateCredentials
(
AuthenticationInfo
authenticationInfo
)
throws
Exception
{
LoginContext
loginContext
=
new
LoginContext
(
appName
,
new
AuthenticationInfoCallbackHandler
(
authenticationInfo
));
loginContext
.
login
();
authenticationInfo
.
setNestedIdentity
(
loginContext
.
getSubject
());
return
true
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/impl/LdapCredentialsValidator.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
.
impl
;
import
java.util.Hashtable
;
import
javax.naming.Context
;
import
javax.naming.directory.DirContext
;
import
javax.naming.directory.InitialDirContext
;
import
org.h2.api.CredentialsValidator
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.ConfigProperties
;
/**
* Validate credentials by performing an LDAP bind
*
* configuration parameters:
* bindDnPattern = bind dn pattern with %u istead of username (example: uid=%u,ou=users,dc=example,dc=com)
* host = ldap host
* port (optional) = ldap port (by default 389 for unsecure, 636 for secure)
* secure (optional) = use ssl (default true)
*/
public
class
LdapCredentialsValidator
implements
CredentialsValidator
{
String
bindDnPattern
;
String
host
;
int
port
;
boolean
secure
;
String
url
;
@Override
public
void
configure
(
ConfigProperties
configProperties
)
{
bindDnPattern
=
configProperties
.
getStringValue
(
"bindDnPattern"
);
host
=
configProperties
.
getStringValue
(
"host"
);
secure
=
configProperties
.
getBooleanValue
(
"secure"
,
true
);
port
=
configProperties
.
getIntValue
(
"port"
,
secure
?
636
:
389
);
url
=
"ldap"
+
(
secure
?
"s"
:
""
)
+
"://"
+
host
+
":"
+
port
;
}
@Override
public
boolean
validateCredentials
(
AuthenticationInfo
authenticationInfo
)
throws
Exception
{
DirContext
dirContext
=
null
;
try
{
String
dn
=
bindDnPattern
.
replace
(
"%u"
,
authenticationInfo
.
getUserName
());
Hashtable
<
String
,
String
>
env
=
new
Hashtable
<>();
env
.
put
(
Context
.
INITIAL_CONTEXT_FACTORY
,
"com.sun.jndi.ldap.LdapCtxFactory"
);
env
.
put
(
Context
.
PROVIDER_URL
,
url
);
env
.
put
(
Context
.
SECURITY_AUTHENTICATION
,
"simple"
);
env
.
put
(
Context
.
SECURITY_PRINCIPAL
,
dn
);
env
.
put
(
Context
.
SECURITY_CREDENTIALS
,
authenticationInfo
.
getPassword
());
if
(
secure
)
{
env
.
put
(
Context
.
SECURITY_PROTOCOL
,
"ssl"
);
}
dirContext
=
new
InitialDirContext
(
env
);
authenticationInfo
.
setNestedIdentity
(
dn
);
return
true
;
}
finally
{
if
(
dirContext
!=
null
)
{
dirContext
.
close
();
}
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/impl/StaticRolesMapper.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
.
impl
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
org.h2.api.UserToRolesMapper
;
import
org.h2.security.auth.AuthenticationException
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.ConfigProperties
;
/**
* Assign static roles to authenticated users
*
* parameters:
* roles = role list separated by comma
*/
public
class
StaticRolesMapper
implements
UserToRolesMapper
{
Collection
<
String
>
roles
;
public
StaticRolesMapper
()
{
}
public
StaticRolesMapper
(
String
...
roles
)
{
this
.
roles
=
Arrays
.
asList
(
roles
);
}
@Override
public
void
configure
(
ConfigProperties
configProperties
)
{
String
rolesString
=
configProperties
.
getStringValue
(
"roles"
,
""
);
if
(
rolesString
!=
null
)
{
roles
=
new
HashSet
<>(
Arrays
.
asList
(
rolesString
.
split
(
","
)));
}
}
@Override
public
Collection
<
String
>
mapUserToRoles
(
AuthenticationInfo
authenticationInfo
)
throws
AuthenticationException
{
return
roles
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/security/auth/impl/StaticUserCredentialsValidator.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* Copyright 2004-2018 H2 Group. Mul tiple-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
.
impl
;
import
java.util.regex.Pattern
;
import
org.h2.api.CredentialsValidator
;
import
org.h2.security.SHA256
;
import
org.h2.security.auth.AuthenticationException
;
import
org.h2.security.auth.AuthenticationInfo
;
import
org.h2.security.auth.ConfigProperties
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
import
org.h2.util.Utils
;
/**
* This credentials validator matches the user and password with the configured
* Usage should be limited to test purposes
*
*/
public
class
StaticUserCredentialsValidator
implements
CredentialsValidator
{
Pattern
userNamePattern
;
String
password
;
byte
[]
salt
;
byte
[]
hashWithSalt
;
public
StaticUserCredentialsValidator
()
{
}
public
StaticUserCredentialsValidator
(
String
userNamePattern
,
String
password
)
{
if
(
userNamePattern
!=
null
)
{
this
.
userNamePattern
=
Pattern
.
compile
(
userNamePattern
.
toUpperCase
());
}
salt
=
MathUtils
.
secureRandomBytes
(
256
);
hashWithSalt
=
SHA256
.
getHashWithSalt
(
password
.
getBytes
(),
salt
);
}
@Override
public
boolean
validateCredentials
(
AuthenticationInfo
authenticationInfo
)
throws
AuthenticationException
{
if
(
userNamePattern
!=
null
)
{
if
(
userNamePattern
.
matcher
(
authenticationInfo
.
getUserName
()).
matches
()==
false
)
{
return
false
;
}
}
if
(
password
!=
null
)
{
return
password
.
equals
(
authenticationInfo
.
getPassword
());
}
return
Utils
.
compareSecure
(
hashWithSalt
,
SHA256
.
getHashWithSalt
(
authenticationInfo
.
getPassword
().
getBytes
(),
salt
));
}
@Override
public
void
configure
(
ConfigProperties
configProperties
)
{
String
userNamePatternString
=
configProperties
.
getStringValue
(
"userNamePattern"
,
null
);
if
(
userNamePatternString
!=
null
)
{
userNamePattern
=
userNamePattern
.
compile
(
userNamePatternString
);
}
password
=
configProperties
.
getStringValue
(
"password"
,
password
);
String
saltString
=
configProperties
.
getStringValue
(
"salt"
,
null
);
if
(
saltString
!=
null
)
{
salt
=
StringUtils
.
convertHexToBytes
(
saltString
);
}
String
hashString
=
configProperties
.
getStringValue
(
"hash"
,
null
);
if
(
hashString
!=
null
)
{
hashWithSalt
=
SHA256
.
getHashWithSalt
(
StringUtils
.
convertHexToBytes
(
hashString
),
salt
);
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/auth/MyLoginModule.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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.Map
;
import
javax.security.auth.Subject
;
import
javax.security.auth.callback.Callback
;
import
javax.security.auth.callback.CallbackHandler
;
import
javax.security.auth.callback.NameCallback
;
import
javax.security.auth.callback.PasswordCallback
;
import
javax.security.auth.login.LoginException
;
import
javax.security.auth.spi.LoginModule
;
public
class
MyLoginModule
implements
LoginModule
{
String
password
;
CallbackHandler
callbackHandler
;
@Override
public
void
initialize
(
Subject
subject
,
CallbackHandler
callbackHandler
,
Map
<
String
,
?>
sharedState
,
Map
<
String
,
?>
options
)
{
this
.
callbackHandler
=
callbackHandler
;
password
=
""
+
options
.
get
(
"password"
);
}
@Override
public
boolean
login
()
throws
LoginException
{
if
(
callbackHandler
==
null
)
{
throw
new
LoginException
(
"no callbackHandler available"
);
}
NameCallback
nameCallback
=
new
NameCallback
(
"user name"
);
PasswordCallback
passwordCallback
=
new
PasswordCallback
(
"user name"
,
false
);
try
{
callbackHandler
.
handle
(
new
Callback
[]
{
nameCallback
,
passwordCallback
});
}
catch
(
Exception
exception
)
{
throw
new
LoginException
(
"an exception occurred during inquiry of username and password"
);
}
return
password
.
equals
(
new
String
(
passwordCallback
.
getPassword
()));
}
@Override
public
boolean
logout
()
throws
LoginException
{
return
true
;
}
@Override
public
boolean
abort
()
throws
LoginException
{
return
true
;
}
@Override
public
boolean
commit
()
throws
LoginException
{
return
true
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/auth/TestAuthentication.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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.sql.Connection
;
import
java.sql.DriverManager
;
import
java.sql.SQLException
;
import
java.util.HashMap
;
import
java.util.Properties
;
import
java.util.UUID
;
import
javax.security.auth.login.AppConfigurationEntry
;
import
javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag
;
import
javax.security.auth.login.Configuration
;
import
org.h2.engine.ConnectionInfo
;
import
org.h2.engine.Database
;
import
org.h2.engine.Engine
;
import
org.h2.engine.Role
;
import
org.h2.engine.Session
;
import
org.h2.engine.User
;
import
org.h2.security.auth.DefaultAuthenticator
;
import
org.h2.security.auth.impl.AssignRealmNameRole
;
import
org.h2.security.auth.impl.JaasCredentialsValidator
;
import
org.h2.security.auth.impl.StaticRolesMapper
;
import
org.h2.security.auth.impl.StaticUserCredentialsValidator
;
import
org.h2.test.TestBase
;
public
class
TestAuthentication
extends
TestBase
{
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
}
String
externalUserPassword
;
String
getExternalUserPassword
()
{
if
(
externalUserPassword
==
null
)
{
externalUserPassword
=
UUID
.
randomUUID
().
toString
();
}
return
externalUserPassword
;
}
String
getRealmName
()
{
return
"testRealm"
;
}
String
getJaasConfigName
()
{
return
"testJaasH2"
;
}
String
getStaticRoleName
()
{
return
"staticRole"
;
}
DefaultAuthenticator
defaultAuthenticator
;
void
configureAuthentication
(
Database
database
)
{
defaultAuthenticator
=
new
DefaultAuthenticator
(
true
);
defaultAuthenticator
.
setAllowUserRegistration
(
true
);
defaultAuthenticator
.
setCreateMissingRoles
(
true
);
defaultAuthenticator
.
addRealm
(
getRealmName
(),
new
JaasCredentialsValidator
(
getJaasConfigName
()));
defaultAuthenticator
.
addRealm
(
getRealmName
()
+
"_STATIC"
,
new
StaticUserCredentialsValidator
(
"staticuser[0-9]"
,
"staticpassword"
));
defaultAuthenticator
.
setUserToRolesMappers
(
new
AssignRealmNameRole
(
"@%s"
),
new
StaticRolesMapper
(
getStaticRoleName
()));
database
.
setAuthenticator
(
defaultAuthenticator
);
}
void
configureJaas
()
{
final
Configuration
innerConfiguration
=
Configuration
.
getConfiguration
();
Configuration
.
setConfiguration
(
new
Configuration
()
{
@Override
public
AppConfigurationEntry
[]
getAppConfigurationEntry
(
String
name
)
{
if
(
name
.
equals
(
getJaasConfigName
()))
{
HashMap
<
String
,
String
>
options
=
new
HashMap
<>();
options
.
put
(
"password"
,
getExternalUserPassword
());
return
new
AppConfigurationEntry
[]
{
new
AppConfigurationEntry
(
MyLoginModule
.
class
.
getName
(),
LoginModuleControlFlag
.
REQUIRED
,
options
)
};
}
return
innerConfiguration
.
getAppConfigurationEntry
(
name
);
}
});
}
protected
String
getDatabaseURL
()
{
return
"jdbc:h2:mem:"
+
getClass
().
getSimpleName
();
}
protected
String
getExternalUser
()
{
return
"user"
;
}
Session
session
;
Database
database
;
@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
{
allTests
();
}
finally
{
session
.
close
();
}
}
finally
{
Configuration
.
setConfiguration
(
oldConfiguration
);
}
}
protected
void
allTests
()
throws
Exception
{
testInvalidPassword
();
testExternalUserWihoutRealm
();
testExternalUser
();
testAssignRealNameRole
();
testStaticRole
();
testStaticUserCredentials
();
testUserRegistration
();
}
protected
void
testInvalidPassword
()
throws
Exception
{
try
{
Connection
wrongLoginConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
(),
getExternalUser
(),
""
);
wrongLoginConnection
.
close
();
throw
new
Exception
(
"user should not be able to login with an invalid password"
);
}
catch
(
SQLException
e
)
{
}
}
protected
void
testExternalUserWihoutRealm
()
throws
Exception
{
try
{
Connection
wrongLoginConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
(),
getExternalUser
(),
getExternalUserPassword
());
wrongLoginConnection
.
close
();
throw
new
Exception
(
"user should not be able to login without a realm"
);
}
catch
(
SQLException
e
)
{
}
}
protected
void
testExternalUser
()
throws
Exception
{
Connection
rightConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
(),
getExternalUser
(),
getExternalUserPassword
());
try
{
User
user
=
session
.
getDatabase
().
findUser
((
getExternalUser
()
+
"@"
+
getRealmName
()).
toUpperCase
());
assertNotNull
(
user
);
}
finally
{
rightConnection
.
close
();
}
}
protected
void
testAssignRealNameRole
()
throws
Exception
{
String
realmNameRoleName
=
"@"
+
getRealmName
().
toUpperCase
();
Role
realmNameRole
=
database
.
findRole
(
realmNameRoleName
);
if
(
realmNameRole
==
null
)
{
realmNameRole
=
new
Role
(
database
,
database
.
allocateObjectId
(),
realmNameRoleName
,
false
);
session
.
getDatabase
().
addDatabaseObject
(
session
,
realmNameRole
);
session
.
commit
(
false
);
}
Connection
rightConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
(),
getExternalUser
(),
getExternalUserPassword
());
try
{
User
user
=
session
.
getDatabase
().
findUser
((
getExternalUser
()
+
"@"
+
getRealmName
()).
toUpperCase
());
assertNotNull
(
user
);
assertTrue
(
user
.
isRoleGranted
(
realmNameRole
));
}
finally
{
rightConnection
.
close
();
}
}
protected
void
testStaticRole
()
throws
Exception
{
Connection
rightConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
(),
getExternalUser
(),
getExternalUserPassword
());
try
{
User
user
=
session
.
getDatabase
().
findUser
((
getExternalUser
()
+
"@"
+
getRealmName
()).
toUpperCase
());
assertNotNull
(
user
);
Role
staticRole
=
session
.
getDatabase
().
findRole
(
getStaticRoleName
());
if
(
staticRole
!=
null
)
{
assertTrue
(
user
.
isRoleGranted
(
staticRole
));
}
}
finally
{
rightConnection
.
close
();
}
}
protected
void
testUserRegistration
()
throws
Exception
{
boolean
initialValueAllow
=
defaultAuthenticator
.
isAllowUserRegistration
();
defaultAuthenticator
.
setAllowUserRegistration
(
false
);
try
{
try
{
Connection
wrongLoginConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
(),
"___"
+
getExternalUser
(),
""
);
wrongLoginConnection
.
close
();
throw
new
Exception
(
"unregistered external users should not be able to login when allowUserRegistration=false"
);
}
catch
(
SQLException
e
)
{
}
String
validUserName
=
"new_"
+
getExternalUser
();
User
validUser
=
new
User
(
database
,
database
.
allocateObjectId
(),
(
validUserName
.
toUpperCase
()
+
"@"
+
getRealmName
()).
toUpperCase
(),
false
);
validUser
.
setUserPasswordHash
(
new
byte
[]
{});
database
.
addDatabaseObject
(
session
,
validUser
);
session
.
commit
(
false
);
Connection
connectionWithRegisterUser
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
(),
validUserName
,
getExternalUserPassword
());
connectionWithRegisterUser
.
close
();
}
finally
{
defaultAuthenticator
.
setAllowUserRegistration
(
initialValueAllow
);
}
}
public
void
testStaticUserCredentials
()
throws
Exception
{
String
userName
=
"STATICUSER3"
;
Connection
rightConnection
=
DriverManager
.
getConnection
(
getDatabaseURL
()
+
";AUTHREALM="
+
getRealmName
().
toUpperCase
()+
"_STATIC"
,
userName
,
"staticpassword"
);
try
{
User
user
=
session
.
getDatabase
().
findUser
(
userName
+
"@"
+
getRealmName
().
toUpperCase
()+
"_STATIC"
);
assertNotNull
(
user
);
}
finally
{
rightConnection
.
close
();
}
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/auth/TestAuthenticationDefaults.java
0 → 100644
浏览文件 @
78b5a2dc
/*
* 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
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论