This is an automated email from the ASF dual-hosted git repository.

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new d0e096ba72a Add authenticator for AuthorityRule (#24121)
d0e096ba72a is described below

commit d0e096ba72ac7af072131168d4b3602b4d6cd437
Author: Liang Zhang <[email protected]>
AuthorDate: Sun Feb 12 09:05:05 2023 +0800

    Add authenticator for AuthorityRule (#24121)
    
    * Fix java doc
    
    * Refactor MySQLAuthenticationHandler and PostgreSQLAuthenticationHandler
    
    * Add authenticator for AuthorityRule
---
 .../infra/metadata/user/ShardingSphereUser.java    |  2 +-
 .../config/AuthorityRuleConfiguration.java         | 21 ++++++++++++++--
 .../authority/model/AuthorityRegistry.java         |  2 +-
 .../authority/model/ShardingSpherePrivileges.java  |  2 +-
 .../authority/rule/AuthorityRule.java              | 22 ++++++++++++++++-
 .../config/YamlAuthorityRuleConfiguration.java     |  6 +++++
 .../YamlAuthorityRuleConfigurationSwapper.java     |  8 ++++++-
 .../authentication/MySQLAuthenticationEngine.java  |  4 ++--
 .../authentication/MySQLAuthenticationHandler.java | 28 ++++++++++++++++++----
 .../MySQLAuthenticationHandlerTest.java            |  6 +++--
 .../PostgreSQLAuthenticationEngine.java            |  8 +++++--
 .../PostgreSQLAuthenticationHandler.java           | 26 ++++++++++++++++----
 .../PostgreSQLAuthenticationHandlerTest.java       |  6 +++--
 13 files changed, 116 insertions(+), 25 deletions(-)

diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/user/ShardingSphereUser.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/user/ShardingSphereUser.java
index 2077f6d91fb..771f6be71db 100644
--- 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/user/ShardingSphereUser.java
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/user/ShardingSphereUser.java
@@ -34,7 +34,7 @@ public final class ShardingSphereUser {
     private final String authenticationMethodName;
     
     public ShardingSphereUser(final String username, final String password, 
final String hostname) {
-        this(username, password, hostname, null);
+        this(username, password, hostname, "");
     }
     
     public ShardingSphereUser(final String username, final String password, 
final String hostname, final String authenticationMethodName) {
diff --git 
a/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/config/AuthorityRuleConfiguration.java
 
b/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/config/AuthorityRuleConfiguration.java
index ded23337fb9..090c91ec63e 100644
--- 
a/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/config/AuthorityRuleConfiguration.java
+++ 
b/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/config/AuthorityRuleConfiguration.java
@@ -18,21 +18,38 @@
 package org.apache.shardingsphere.authority.config;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
 import 
org.apache.shardingsphere.infra.config.rule.scope.GlobalRuleConfiguration;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 /**
  * Authority rule configuration.
  */
-@RequiredArgsConstructor
 @Getter
+@Setter
 public final class AuthorityRuleConfiguration implements 
GlobalRuleConfiguration {
     
     private final Collection<ShardingSphereUser> users;
     
     private final AlgorithmConfiguration provider;
+    
+    private final Map<String, AlgorithmConfiguration> authenticators = new 
LinkedHashMap<>();
+    
+    private String defaultAuthenticator;
+    
+    public AuthorityRuleConfiguration(final Collection<ShardingSphereUser> 
users, final AlgorithmConfiguration provider) {
+        this.users = users;
+        this.provider = provider;
+    }
+    
+    public AuthorityRuleConfiguration(final Collection<ShardingSphereUser> 
users, final AlgorithmConfiguration provider, final String 
defaultAuthenticator) {
+        this.users = users;
+        this.provider = provider;
+        this.defaultAuthenticator = defaultAuthenticator;
+    }
 }
diff --git 
a/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/AuthorityRegistry.java
 
b/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/AuthorityRegistry.java
index 4bdb833e8c1..8c73f9a77bc 100644
--- 
a/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/AuthorityRegistry.java
+++ 
b/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/AuthorityRegistry.java
@@ -27,7 +27,7 @@ import java.util.Optional;
 public interface AuthorityRegistry {
     
     /**
-     * Find Privileges.
+     * Find privileges.
      *
      * @param grantee grantee
      * @return found privileges
diff --git 
a/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/ShardingSpherePrivileges.java
 
b/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/ShardingSpherePrivileges.java
index d8fc42341ca..daabf949f64 100644
--- 
a/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/ShardingSpherePrivileges.java
+++ 
b/kernel/authority/api/src/main/java/org/apache/shardingsphere/authority/model/ShardingSpherePrivileges.java
@@ -20,7 +20,7 @@ package org.apache.shardingsphere.authority.model;
 import java.util.Collection;
 
 /**
- * ShardingSphere Privileges.
+ * ShardingSphere privileges.
  */
 public interface ShardingSpherePrivileges {
     
diff --git 
a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/rule/AuthorityRule.java
 
b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/rule/AuthorityRule.java
index 714bf2ebb63..45e6b43d2ca 100644
--- 
a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/rule/AuthorityRule.java
+++ 
b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/rule/AuthorityRule.java
@@ -22,6 +22,7 @@ import 
org.apache.shardingsphere.authority.config.AuthorityRuleConfiguration;
 import org.apache.shardingsphere.authority.model.AuthorityRegistry;
 import org.apache.shardingsphere.authority.model.ShardingSpherePrivileges;
 import org.apache.shardingsphere.authority.spi.AuthorityProvider;
+import org.apache.shardingsphere.infra.config.algorithm.AlgorithmConfiguration;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.user.Grantee;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
@@ -29,6 +30,7 @@ import 
org.apache.shardingsphere.infra.rule.identifier.scope.GlobalRule;
 import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Optional;
 
@@ -46,16 +48,22 @@ public final class AuthorityRule implements GlobalRule {
     
     private volatile AuthorityRegistry authorityRegistry;
     
+    private final Map<String, AlgorithmConfiguration> authenticatorConfig = 
new LinkedHashMap<>();
+    
+    private final String defaultAuthenticator;
+    
     public AuthorityRule(final AuthorityRuleConfiguration ruleConfig, final 
Map<String, ShardingSphereDatabase> databases) {
         configuration = ruleConfig;
         users = ruleConfig.getUsers();
         provider = TypedSPILoader.getService(AuthorityProvider.class, 
ruleConfig.getProvider().getType(), ruleConfig.getProvider().getProps());
         authorityRegistry = provider.buildAuthorityRegistry(databases, 
ruleConfig.getUsers());
+        authenticatorConfig.putAll(ruleConfig.getAuthenticators());
+        defaultAuthenticator = ruleConfig.getDefaultAuthenticator();
     }
     
     /**
      * Find user.
-     * 
+     *
      * @param grantee grantee user
      * @return user
      */
@@ -83,6 +91,18 @@ public final class AuthorityRule implements GlobalRule {
         authorityRegistry = provider.buildAuthorityRegistry(databases, users);
     }
     
+    /**
+     * Get authenticator type.
+     * 
+     * @param user user
+     * @return authenticator type
+     */
+    public String getAuthenticatorType(final ShardingSphereUser user) {
+        return 
authenticatorConfig.containsKey(user.getAuthenticationMethodName())
+                ? 
authenticatorConfig.get(user.getAuthenticationMethodName()).getType()
+                : Optional.ofNullable(defaultAuthenticator).orElse("");
+    }
+    
     @Override
     public String getType() {
         return AuthorityRule.class.getSimpleName();
diff --git 
a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/config/YamlAuthorityRuleConfiguration.java
 
b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/config/YamlAuthorityRuleConfiguration.java
index d3395a9ea3f..bd876836e6f 100644
--- 
a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/config/YamlAuthorityRuleConfiguration.java
+++ 
b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/config/YamlAuthorityRuleConfiguration.java
@@ -25,7 +25,9 @@ import 
org.apache.shardingsphere.infra.yaml.config.pojo.algorithm.YamlAlgorithmC
 import 
org.apache.shardingsphere.infra.yaml.config.pojo.rule.YamlGlobalRuleConfiguration;
 
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
+import java.util.Map;
 
 /**
  * Authority rule configuration for YAML.
@@ -38,6 +40,10 @@ public final class YamlAuthorityRuleConfiguration implements 
YamlGlobalRuleConfi
     
     private YamlAlgorithmConfiguration privilege;
     
+    private Map<String, YamlAlgorithmConfiguration> authenticators = new 
LinkedHashMap<>();
+    
+    private String defaultAuthenticator;
+    
     @Override
     public Class<AuthorityRuleConfiguration> getRuleConfigurationType() {
         return AuthorityRuleConfiguration.class;
diff --git 
a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/swapper/YamlAuthorityRuleConfigurationSwapper.java
 
b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/swapper/YamlAuthorityRuleConfigurationSwapper.java
index df0ed9a430f..beec7892d27 100644
--- 
a/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/swapper/YamlAuthorityRuleConfigurationSwapper.java
+++ 
b/kernel/authority/core/src/main/java/org/apache/shardingsphere/authority/yaml/swapper/YamlAuthorityRuleConfigurationSwapper.java
@@ -41,6 +41,10 @@ public final class YamlAuthorityRuleConfigurationSwapper 
implements YamlRuleConf
         YamlAuthorityRuleConfiguration result = new 
YamlAuthorityRuleConfiguration();
         
result.setPrivilege(algorithmSwapper.swapToYamlConfiguration(data.getProvider()));
         
result.setUsers(YamlUsersConfigurationConverter.convertToYamlUserConfiguration(data.getUsers()));
+        result.setDefaultAuthenticator(data.getDefaultAuthenticator());
+        if (!data.getAuthenticators().isEmpty()) {
+            data.getAuthenticators().forEach((key, value) -> 
result.getAuthenticators().put(key, 
algorithmSwapper.swapToYamlConfiguration(value)));
+        }
         return result;
     }
     
@@ -51,7 +55,9 @@ public final class YamlAuthorityRuleConfigurationSwapper 
implements YamlRuleConf
         if (null == provider) {
             provider = new 
DefaultAuthorityRuleConfigurationBuilder().build().getProvider();
         }
-        return new AuthorityRuleConfiguration(users, provider);
+        AuthorityRuleConfiguration result = new 
AuthorityRuleConfiguration(users, provider, 
yamlConfig.getDefaultAuthenticator());
+        yamlConfig.getAuthenticators().forEach((key, value) -> 
result.getAuthenticators().put(key, algorithmSwapper.swapToObject(value)));
+        return result;
     }
     
     @Override
diff --git 
a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
 
b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
index c9517ec843d..eca0d2c44aa 100644
--- 
a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
+++ 
b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
@@ -35,7 +35,7 @@ import 
org.apache.shardingsphere.db.protocol.mysql.packet.handshake.MySQLHandsha
 import org.apache.shardingsphere.db.protocol.mysql.payload.MySQLPacketPayload;
 import org.apache.shardingsphere.db.protocol.payload.PacketPayload;
 import org.apache.shardingsphere.dialect.mysql.vendor.MySQLVendorError;
-import org.apache.shardingsphere.infra.metadata.user.Grantee;
+import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import 
org.apache.shardingsphere.proxy.frontend.authentication.AuthenticationEngine;
 import 
org.apache.shardingsphere.proxy.frontend.authentication.AuthenticationResult;
@@ -104,7 +104,7 @@ public final class MySQLAuthenticationEngine implements 
AuthenticationEngine {
             return AuthenticationResultBuilder.continued();
         }
         AuthorityRule rule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
-        MySQLAuthenticator authenticator = 
authenticationHandler.getAuthenticator(rule, new Grantee(packet.getUsername(), 
getHostAddress(context)));
+        MySQLAuthenticator authenticator = 
authenticationHandler.getAuthenticator(rule, new 
ShardingSphereUser(packet.getUsername(), "", getHostAddress(context)));
         if (isClientPluginAuth(packet) && 
!authenticator.getAuthenticationMethodName().equals(packet.getAuthPluginName()))
 {
             connectionPhase = 
MySQLConnectionPhase.AUTHENTICATION_METHOD_MISMATCH;
             context.writeAndFlush(new 
MySQLAuthSwitchRequestPacket(authenticator.getAuthenticationMethodName(), 
authenticationHandler.getAuthPluginData()));
diff --git 
a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
 
b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
index 609acf5fa94..6557629da69 100644
--- 
a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
+++ 
b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandler.java
@@ -20,12 +20,14 @@ package 
org.apache.shardingsphere.proxy.frontend.mysql.authentication;
 import lombok.Getter;
 import org.apache.shardingsphere.authority.checker.AuthorityChecker;
 import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import 
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLAuthenticationMethod;
 import 
org.apache.shardingsphere.db.protocol.mysql.packet.handshake.MySQLAuthPluginData;
 import org.apache.shardingsphere.dialect.mysql.vendor.MySQLVendorError;
 import org.apache.shardingsphere.infra.metadata.user.Grantee;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import 
org.apache.shardingsphere.proxy.frontend.mysql.authentication.authenticator.MySQLAuthenticator;
+import 
org.apache.shardingsphere.proxy.frontend.mysql.authentication.authenticator.MySQLClearPasswordAuthenticator;
 import 
org.apache.shardingsphere.proxy.frontend.mysql.authentication.authenticator.MySQLNativePasswordAuthenticator;
 
 import java.util.Optional;
@@ -51,7 +53,7 @@ public final class MySQLAuthenticationHandler {
         AuthorityRule rule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
         Grantee grantee = new Grantee(username, hostname);
         Optional<ShardingSphereUser> user = rule.findUser(grantee);
-        if (!user.isPresent() || !getAuthenticator(rule, 
grantee).authenticate(user.get(), authenticationResponse)) {
+        if (!user.isPresent() || !getAuthenticator(rule, 
user.get()).authenticate(user.get(), authenticationResponse)) {
             return Optional.of(MySQLVendorError.ER_ACCESS_DENIED_ERROR);
         }
         return null == databaseName || new AuthorityChecker(rule, 
grantee).isAuthorized(databaseName) ? Optional.empty() : 
Optional.of(MySQLVendorError.ER_DBACCESS_DENIED_ERROR);
@@ -61,11 +63,27 @@ public final class MySQLAuthenticationHandler {
      * Get authenticator.
      *
      * @param rule authority rule
-     * @param grantee grantee
+     * @param user user
      * @return authenticator
      */
-    public MySQLAuthenticator getAuthenticator(final AuthorityRule rule, final 
Grantee grantee) {
-        // TODO use authority rule and grantee to determine authentication 
method
-        return new MySQLNativePasswordAuthenticator(authPluginData);
+    public MySQLAuthenticator getAuthenticator(final AuthorityRule rule, final 
ShardingSphereUser user) {
+        MySQLAuthenticationMethod authenticationMethod;
+        try {
+            authenticationMethod = 
MySQLAuthenticationMethod.valueOf(rule.getAuthenticatorType(user).toUpperCase());
+        } catch (final IllegalArgumentException ignored) {
+            return new MySQLNativePasswordAuthenticator(authPluginData);
+        }
+        switch (authenticationMethod) {
+            case SECURE_PASSWORD_AUTHENTICATION:
+                return new MySQLNativePasswordAuthenticator(authPluginData);
+            case CLEAR_TEXT_AUTHENTICATION:
+                return new MySQLClearPasswordAuthenticator();
+            // TODO add other Authenticator
+            case OLD_PASSWORD_AUTHENTICATION:
+            case WINDOWS_NATIVE_AUTHENTICATION:
+            case SHA256:
+            default:
+                return new MySQLNativePasswordAuthenticator(authPluginData);
+        }
     }
 }
diff --git 
a/proxy/frontend/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandlerTest.java
 
b/proxy/frontend/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandlerTest.java
index 8041a668779..982c0746f8c 100644
--- 
a/proxy/frontend/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandlerTest.java
+++ 
b/proxy/frontend/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationHandlerTest.java
@@ -31,7 +31,6 @@ import 
org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
-import org.apache.shardingsphere.infra.metadata.user.Grantee;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
@@ -121,7 +120,10 @@ public final class MySQLAuthenticationHandlerTest extends 
ProxyContextRestorer {
     
     @Test
     public void assertGetAuthenticator() {
-        MySQLAuthenticator authenticator = 
authenticationHandler.getAuthenticator(mock(AuthorityRule.class), new 
Grantee("root", ""));
+        ShardingSphereUser user = new ShardingSphereUser("root", "", "");
+        AuthorityRule rule = mock(AuthorityRule.class);
+        when(rule.getAuthenticatorType(user)).thenReturn("");
+        MySQLAuthenticator authenticator = 
authenticationHandler.getAuthenticator(rule, user);
         assertThat(authenticator, 
instanceOf(MySQLNativePasswordAuthenticator.class));
         assertThat(authenticator.getAuthenticationMethodName(), 
is(MySQLAuthenticationMethod.SECURE_PASSWORD_AUTHENTICATION.getMethodName()));
     }
diff --git 
a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationEngine.java
 
b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationEngine.java
index 564b11ffacb..62ed7a39348 100644
--- 
a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationEngine.java
+++ 
b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationEngine.java
@@ -39,6 +39,7 @@ import 
org.apache.shardingsphere.db.protocol.postgresql.payload.PostgreSQLPacket
 import 
org.apache.shardingsphere.dialect.postgresql.exception.authority.EmptyUsernameException;
 import 
org.apache.shardingsphere.dialect.postgresql.exception.protocol.ProtocolViolationException;
 import org.apache.shardingsphere.infra.metadata.user.Grantee;
+import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.postgresql.PostgreSQLCharacterSets;
 import 
org.apache.shardingsphere.proxy.frontend.authentication.AuthenticationEngine;
@@ -47,6 +48,8 @@ import 
org.apache.shardingsphere.proxy.frontend.authentication.AuthenticationRes
 import 
org.apache.shardingsphere.proxy.frontend.connection.ConnectionIdGenerator;
 import 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication.authenticator.PostgreSQLAuthenticator;
 
+import java.util.Optional;
+
 /**
  * Authentication engine for PostgreSQL.
  */
@@ -115,8 +118,9 @@ public final class PostgreSQLAuthenticationEngine 
implements AuthenticationEngin
     
     private PostgreSQLIdentifierPacket getIdentifierPacket(final String 
username) {
         AuthorityRule rule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
-        PostgreSQLAuthenticator authenticator = 
authenticationHandler.getAuthenticator(rule, new Grantee(username, ""));
-        if 
(PostgreSQLAuthenticationMethod.PASSWORD.getMethodName().equals(authenticator.getAuthenticationMethodName()))
 {
+        Optional<ShardingSphereUser> user = rule.findUser(new 
Grantee(username, ""));
+        Optional<PostgreSQLAuthenticator> authenticator = user.map(optional -> 
authenticationHandler.getAuthenticator(rule, optional));
+        if (authenticator.isPresent() && 
PostgreSQLAuthenticationMethod.PASSWORD.getMethodName().equals(authenticator.get().getAuthenticationMethodName()))
 {
             return new PostgreSQLPasswordAuthenticationPacket();
         }
         md5Salt = 
PostgreSQLRandomGenerator.getInstance().generateRandomBytes(4);
diff --git 
a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
 
b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
index 5591b96e6f5..ecbadb10c05 100644
--- 
a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
+++ 
b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandler.java
@@ -20,6 +20,7 @@ package 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication;
 import com.google.common.base.Strings;
 import org.apache.shardingsphere.authority.checker.AuthorityChecker;
 import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import 
org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLAuthenticationMethod;
 import 
org.apache.shardingsphere.db.protocol.postgresql.packet.handshake.PostgreSQLPasswordMessagePacket;
 import 
org.apache.shardingsphere.dialect.exception.syntax.database.UnknownDatabaseException;
 import 
org.apache.shardingsphere.dialect.postgresql.exception.authority.InvalidPasswordException;
@@ -31,6 +32,7 @@ import 
org.apache.shardingsphere.infra.util.exception.ShardingSpherePrecondition
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication.authenticator.PostgreSQLAuthenticator;
 import 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication.authenticator.PostgreSQLMD5PasswordAuthenticator;
+import 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication.authenticator.PostgreSQLPasswordAuthenticator;
 
 import java.util.Optional;
 
@@ -53,7 +55,7 @@ public final class PostgreSQLAuthenticationHandler {
         Grantee grantee = new Grantee(username, "%");
         Optional<ShardingSphereUser> user = rule.findUser(grantee);
         ShardingSpherePreconditions.checkState(user.isPresent(), () -> new 
UnknownUsernameException(username));
-        ShardingSpherePreconditions.checkState(getAuthenticator(rule, 
grantee).authenticate(user.get(), new 
Object[]{passwordMessagePacket.getDigest(), md5Salt}),
+        ShardingSpherePreconditions.checkState(getAuthenticator(rule, 
user.get()).authenticate(user.get(), new 
Object[]{passwordMessagePacket.getDigest(), md5Salt}),
                 () -> new InvalidPasswordException(username));
         ShardingSpherePreconditions.checkState(null == databaseName || new 
AuthorityChecker(rule, grantee).isAuthorized(databaseName),
                 () -> new PrivilegeNotGrantedException(username, 
databaseName));
@@ -63,11 +65,25 @@ public final class PostgreSQLAuthenticationHandler {
      * Get authenticator.
      *
      * @param rule authority rule
-     * @param grantee username
+     * @param user user
      * @return authenticator
      */
-    public PostgreSQLAuthenticator getAuthenticator(final AuthorityRule rule, 
final Grantee grantee) {
-        // TODO use authority rule and grantee to determine authentication 
method
-        return new PostgreSQLMD5PasswordAuthenticator();
+    public PostgreSQLAuthenticator getAuthenticator(final AuthorityRule rule, 
final ShardingSphereUser user) {
+        PostgreSQLAuthenticationMethod authenticationMethod;
+        try {
+            authenticationMethod = 
PostgreSQLAuthenticationMethod.valueOf(rule.getAuthenticatorType(user).toUpperCase());
+        } catch (final IllegalArgumentException ignored) {
+            return new PostgreSQLMD5PasswordAuthenticator();
+        }
+        switch (authenticationMethod) {
+            case MD5:
+                return new PostgreSQLMD5PasswordAuthenticator();
+            case PASSWORD:
+                return new PostgreSQLPasswordAuthenticator();
+            case SCRAM_SHA256:
+                // TODO add SCRAM_SHA256 Authenticator
+            default:
+                return new PostgreSQLMD5PasswordAuthenticator();
+        }
     }
 }
diff --git 
a/proxy/frontend/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandlerTest.java
 
b/proxy/frontend/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandlerTest.java
index 784b2f702de..f57e125c26a 100644
--- 
a/proxy/frontend/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandlerTest.java
+++ 
b/proxy/frontend/postgresql/src/test/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/PostgreSQLAuthenticationHandlerTest.java
@@ -37,7 +37,6 @@ import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
-import org.apache.shardingsphere.infra.metadata.user.Grantee;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
@@ -112,7 +111,10 @@ public final class PostgreSQLAuthenticationHandlerTest 
extends ProxyContextResto
     
     @Test
     public void assertGetAuthenticator() {
-        PostgreSQLAuthenticator authenticator = new 
PostgreSQLAuthenticationHandler().getAuthenticator(mock(AuthorityRule.class), 
new Grantee(username, ""));
+        ShardingSphereUser user = new ShardingSphereUser(username, "", "");
+        AuthorityRule rule = mock(AuthorityRule.class);
+        when(rule.getAuthenticatorType(user)).thenReturn("");
+        PostgreSQLAuthenticator authenticator = new 
PostgreSQLAuthenticationHandler().getAuthenticator(rule, user);
         assertThat(authenticator, 
instanceOf(PostgreSQLMD5PasswordAuthenticator.class));
         assertThat(authenticator.getAuthenticationMethodName(), 
is(PostgreSQLAuthenticationMethod.MD5.getMethodName()));
     }

Reply via email to