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 f2bac7c7403 Add AuthenticatorFactory (#24132)
f2bac7c7403 is described below

commit f2bac7c74039b2eb37c9a373bfedc4a10d7a58c5
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Feb 13 11:05:51 2023 +0800

    Add AuthenticatorFactory (#24132)
---
 .../mysql/constant/MySQLAuthenticationMethod.java  |  2 +-
 .../constant/OpenGaussAuthenticationMethod.java}   | 12 +--
 .../constant/PostgreSQLAuthenticationMethod.java   |  2 +-
 .../authentication/MySQLAuthenticationHandler.java | 23 +-----
 .../authenticator/MySQLAuthenticatorFactory.java   | 91 ++++++++++++++++++++++
 .../OpenGaussAuthenticationHandler.java            | 15 ++--
 .../OpenGaussAuthenticatorFactory.java             | 76 ++++++++++++++++++
 .../PostgreSQLAuthenticationHandler.java           | 21 +----
 .../PostgreSQLAuthenticatorFactory.java            | 85 ++++++++++++++++++++
 9 files changed, 268 insertions(+), 59 deletions(-)

diff --git 
a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLAuthenticationMethod.java
 
b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLAuthenticationMethod.java
index 3aec7fd4636..ec98feacbbe 100644
--- 
a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLAuthenticationMethod.java
+++ 
b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLAuthenticationMethod.java
@@ -22,7 +22,7 @@ import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.db.protocol.constant.AuthenticationMethod;
 
 /**
- * MySQL client/server protocol authentication method.
+ * Authentication method for MySQL.
  *
  * @see <a 
href="https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_authentication_methods.html";>Authentication
 Method</a>
  */
diff --git 
a/db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
 
b/db-protocol/opengauss/src/main/java/org/apache/shardingsphere/db/protocol/opengauss/constant/OpenGaussAuthenticationMethod.java
similarity index 75%
copy from 
db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
copy to 
db-protocol/opengauss/src/main/java/org/apache/shardingsphere/db/protocol/opengauss/constant/OpenGaussAuthenticationMethod.java
index 18425e37c76..f608aaa616f 100644
--- 
a/db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
+++ 
b/db-protocol/opengauss/src/main/java/org/apache/shardingsphere/db/protocol/opengauss/constant/OpenGaussAuthenticationMethod.java
@@ -15,24 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.db.protocol.postgresql.constant;
+package org.apache.shardingsphere.db.protocol.opengauss.constant;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.db.protocol.constant.AuthenticationMethod;
 
 /**
- * PostgreSQL password authentication method.
- *
- * @see <a 
href="https://www.postgresql.org/docs/14/auth-password.html";>Password 
Authentication</a>
+ * Authentication method for openGauss.
  */
 @RequiredArgsConstructor
 @Getter
-public enum PostgreSQLAuthenticationMethod implements AuthenticationMethod {
-    
-    MD5("md5"),
-    
-    PASSWORD("password"),
+public enum OpenGaussAuthenticationMethod implements AuthenticationMethod {
     
     SCRAM_SHA256("scram-sha-256");
     
diff --git 
a/db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
 
b/db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
index 18425e37c76..9642bbe5846 100644
--- 
a/db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
+++ 
b/db-protocol/postgresql/src/main/java/org/apache/shardingsphere/db/protocol/postgresql/constant/PostgreSQLAuthenticationMethod.java
@@ -22,7 +22,7 @@ import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.db.protocol.constant.AuthenticationMethod;
 
 /**
- * PostgreSQL password authentication method.
+ * Authentication method for PostgreSQL.
  *
  * @see <a 
href="https://www.postgresql.org/docs/14/auth-password.html";>Password 
Authentication</a>
  */
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 3d18e275144..19cc8b148f5 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,15 +20,13 @@ 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 
org.apache.shardingsphere.proxy.frontend.mysql.authentication.authenticator.MySQLAuthenticatorFactory;
 
 import java.util.Optional;
 
@@ -67,23 +65,6 @@ public final class MySQLAuthenticationHandler {
      * @return authenticator
      */
     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();
-        }
-        switch (authenticationMethod) {
-            case NATIVE:
-                return new MySQLNativePasswordAuthenticator();
-            case CLEAR_TEXT:
-                return new MySQLClearPasswordAuthenticator();
-            // TODO add other Authenticator
-            case OLD_PASSWORD:
-            case WINDOWS_NATIVE:
-            case SHA256:
-            default:
-                return new MySQLNativePasswordAuthenticator();
-        }
+        return 
MySQLAuthenticatorFactory.createAuthenticator(rule.getAuthenticatorType(user), 
rule);
     }
 }
diff --git 
a/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/authenticator/MySQLAuthenticatorFactory.java
 
b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/authenticator/MySQLAuthenticatorFactory.java
new file mode 100644
index 00000000000..e9dbc28d104
--- /dev/null
+++ 
b/proxy/frontend/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/authenticator/MySQLAuthenticatorFactory.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.proxy.frontend.mysql.authentication.authenticator;
+
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import 
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLAuthenticationMethod;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Authenticator factory for MySQL.
+ */
+@RequiredArgsConstructor
+public enum MySQLAuthenticatorFactory {
+    
+    // TODO impl OLD_PASSWORD Authenticator
+    OLD_PASSWORD(MySQLAuthenticationMethod.OLD_PASSWORD, 
MySQLNativePasswordAuthenticator.class),
+    
+    NATIVE(MySQLAuthenticationMethod.NATIVE, 
MySQLNativePasswordAuthenticator.class, true),
+    
+    CLEAR_TEXT(MySQLAuthenticationMethod.CLEAR_TEXT, 
MySQLClearPasswordAuthenticator.class),
+    
+    // TODO impl WINDOWS_NATIVE Authenticator
+    WINDOWS_NATIVE(MySQLAuthenticationMethod.WINDOWS_NATIVE, 
MySQLNativePasswordAuthenticator.class),
+    
+    // TODO impl SHA256 Authenticator
+    SHA256(MySQLAuthenticationMethod.SHA256, 
MySQLNativePasswordAuthenticator.class);
+    
+    private final MySQLAuthenticationMethod authenticationMethod;
+    
+    private final Class<? extends MySQLAuthenticator> authenticatorClass;
+    
+    private final boolean isDefault;
+    
+    MySQLAuthenticatorFactory(final MySQLAuthenticationMethod 
authenticationMethod, final Class<? extends MySQLAuthenticator> 
authenticatorClass) {
+        this(authenticationMethod, authenticatorClass, false);
+    }
+    
+    /**
+     * Create authenticator.
+     * 
+     * @param authenticationMethod authentication method
+     * @param rule authority rule
+     * @return created authenticator
+     */
+    @SneakyThrows(ReflectiveOperationException.class)
+    public static MySQLAuthenticator createAuthenticator(final String 
authenticationMethod, final AuthorityRule rule) {
+        MySQLAuthenticatorFactory factory = 
findAuthenticatorFactory(getAuthenticator(authenticationMethod));
+        try {
+            return factory.authenticatorClass.getConstructor().newInstance();
+        } catch (final NoSuchMethodException ignored) {
+            return 
factory.authenticatorClass.getConstructor(AuthorityRule.class).newInstance(rule);
+        }
+    }
+    
+    private static MySQLAuthenticationMethod getAuthenticator(final String 
authenticationMethod) {
+        try {
+            return 
MySQLAuthenticationMethod.valueOf(authenticationMethod.toUpperCase());
+        } catch (final IllegalArgumentException ignored) {
+            return getDefaultAuthenticatorFactory().authenticationMethod;
+        }
+    }
+    
+    private static MySQLAuthenticatorFactory findAuthenticatorFactory(final 
MySQLAuthenticationMethod authenticationMethod) {
+        Optional<MySQLAuthenticatorFactory> matchedFactory = 
Arrays.stream(MySQLAuthenticatorFactory.values()).filter(each -> 
each.authenticationMethod == authenticationMethod).findAny();
+        return 
matchedFactory.orElseGet(MySQLAuthenticatorFactory::getDefaultAuthenticatorFactory);
+    }
+    
+    private static MySQLAuthenticatorFactory getDefaultAuthenticatorFactory() {
+        Optional<MySQLAuthenticatorFactory> defaultFactory = 
Arrays.stream(MySQLAuthenticatorFactory.values()).filter(each -> 
each.isDefault).findAny();
+        return defaultFactory.orElseThrow(IllegalArgumentException::new);
+    }
+}
diff --git 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
index 6c672a70006..e1926269027 100644
--- 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
+++ 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
@@ -33,7 +33,7 @@ import 
org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import 
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussAuthenticator;
-import 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussSCRAMSha256PasswordAuthenticator;
+import 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussAuthenticatorFactory;
 
 import javax.crypto.Mac;
 import javax.crypto.SecretKeyFactory;
@@ -137,18 +137,17 @@ public final class OpenGaussAuthenticationHandler {
     public static void loginWithSCRAMSha256Password(final String username, 
final String databaseName, final String salt, final String nonce, final int 
serverIteration,
                                                     final 
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
         
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) || 
ProxyContext.getInstance().databaseExists(databaseName), () -> new 
UnknownDatabaseException(databaseName));
-        AuthorityRule authorityRule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
+        AuthorityRule rule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
         Grantee grantee = new Grantee(username, "%");
-        Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
+        Optional<ShardingSphereUser> user = rule.findUser(grantee);
         ShardingSpherePreconditions.checkState(user.isPresent(), () -> new 
UnknownUsernameException(username));
-        
ShardingSpherePreconditions.checkState(getAuthenticator(grantee).authenticate(user.get(),
 new Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
+        ShardingSpherePreconditions.checkState(getAuthenticator(rule, 
user.get()).authenticate(user.get(), new 
Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
                 () -> new InvalidPasswordException(username));
-        ShardingSpherePreconditions.checkState(null == databaseName || new 
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
+        ShardingSpherePreconditions.checkState(null == databaseName || new 
AuthorityChecker(rule, grantee).isAuthorized(databaseName),
                 () -> new PrivilegeNotGrantedException(username, 
databaseName));
     }
     
-    private static OpenGaussAuthenticator getAuthenticator(final Grantee 
grantee) {
-        // TODO get authenticator by username and hostname
-        return new OpenGaussSCRAMSha256PasswordAuthenticator();
+    private static OpenGaussAuthenticator getAuthenticator(final AuthorityRule 
rule, final ShardingSphereUser user) {
+        return 
OpenGaussAuthenticatorFactory.createAuthenticator(rule.getAuthenticatorType(user),
 rule);
     }
 }
diff --git 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticatorFactory.java
 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticatorFactory.java
new file mode 100644
index 00000000000..24e56cffbda
--- /dev/null
+++ 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticatorFactory.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator;
+
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import 
org.apache.shardingsphere.db.protocol.opengauss.constant.OpenGaussAuthenticationMethod;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Authenticator factory for openGauss.
+ */
+@RequiredArgsConstructor
+public enum OpenGaussAuthenticatorFactory {
+    
+    SCRAM_SHA256(OpenGaussAuthenticationMethod.SCRAM_SHA256, 
OpenGaussSCRAMSha256PasswordAuthenticator.class, true);
+    
+    private final OpenGaussAuthenticationMethod authenticationMethod;
+    
+    private final Class<? extends OpenGaussAuthenticator> authenticatorClass;
+    
+    private final boolean isDefault;
+    
+    /**
+     * Create authenticator.
+     * 
+     * @param authenticationMethod authentication method
+     * @param rule authority rule
+     * @return created authenticator
+     */
+    @SneakyThrows(ReflectiveOperationException.class)
+    public static OpenGaussAuthenticator createAuthenticator(final String 
authenticationMethod, final AuthorityRule rule) {
+        OpenGaussAuthenticatorFactory factory = 
findAuthenticatorFactory(getAuthenticator(authenticationMethod));
+        try {
+            return factory.authenticatorClass.getConstructor().newInstance();
+        } catch (final NoSuchMethodException ignored) {
+            return 
factory.authenticatorClass.getConstructor(AuthorityRule.class).newInstance(rule);
+        }
+    }
+    
+    private static OpenGaussAuthenticationMethod getAuthenticator(final String 
authenticationMethod) {
+        try {
+            return 
OpenGaussAuthenticationMethod.valueOf(authenticationMethod.toUpperCase());
+        } catch (final IllegalArgumentException ignored) {
+            return getDefaultAuthenticatorFactory().authenticationMethod;
+        }
+    }
+    
+    private static OpenGaussAuthenticatorFactory 
findAuthenticatorFactory(final OpenGaussAuthenticationMethod 
authenticationMethod) {
+        Optional<OpenGaussAuthenticatorFactory> matchedFactory = 
Arrays.stream(OpenGaussAuthenticatorFactory.values()).filter(each -> 
each.authenticationMethod == authenticationMethod).findAny();
+        return 
matchedFactory.orElseGet(OpenGaussAuthenticatorFactory::getDefaultAuthenticatorFactory);
+    }
+    
+    private static OpenGaussAuthenticatorFactory 
getDefaultAuthenticatorFactory() {
+        Optional<OpenGaussAuthenticatorFactory> defaultFactory = 
Arrays.stream(OpenGaussAuthenticatorFactory.values()).filter(each -> 
each.isDefault).findAny();
+        return defaultFactory.orElseThrow(IllegalArgumentException::new);
+    }
+}
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 ecbadb10c05..f5ae9a15cf8 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,7 +20,6 @@ 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,8 +30,7 @@ import 
org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import 
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 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 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication.authenticator.PostgreSQLAuthenticatorFactory;
 
 import java.util.Optional;
 
@@ -69,21 +67,6 @@ public final class PostgreSQLAuthenticationHandler {
      * @return authenticator
      */
     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();
-        }
+        return 
PostgreSQLAuthenticatorFactory.createAuthenticator(rule.getAuthenticatorType(user),
 rule);
     }
 }
diff --git 
a/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/authenticator/PostgreSQLAuthenticatorFactory.java
 
b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/authenticator/PostgreSQLAuthenticatorFactory.java
new file mode 100644
index 00000000000..1a1e9ddc54e
--- /dev/null
+++ 
b/proxy/frontend/postgresql/src/main/java/org/apache/shardingsphere/proxy/frontend/postgresql/authentication/authenticator/PostgreSQLAuthenticatorFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.proxy.frontend.postgresql.authentication.authenticator;
+
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import org.apache.shardingsphere.authority.rule.AuthorityRule;
+import 
org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLAuthenticationMethod;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Authenticator factory for PostgreSQL.
+ */
+@RequiredArgsConstructor
+public enum PostgreSQLAuthenticatorFactory {
+    
+    MD5(PostgreSQLAuthenticationMethod.MD5, 
PostgreSQLMD5PasswordAuthenticator.class, true),
+    
+    PASSWORD(PostgreSQLAuthenticationMethod.PASSWORD, 
PostgreSQLPasswordAuthenticator.class),
+    
+    // TODO impl SCRAM_SHA256 Authenticator
+    SCRAM_SHA256(PostgreSQLAuthenticationMethod.SCRAM_SHA256, 
PostgreSQLMD5PasswordAuthenticator.class);
+    
+    private final PostgreSQLAuthenticationMethod authenticationMethod;
+    
+    private final Class<? extends PostgreSQLAuthenticator> authenticatorClass;
+    
+    private final boolean isDefault;
+    
+    PostgreSQLAuthenticatorFactory(final PostgreSQLAuthenticationMethod 
authenticationMethod, final Class<? extends PostgreSQLAuthenticator> 
authenticatorClass) {
+        this(authenticationMethod, authenticatorClass, false);
+    }
+    
+    /**
+     * Create authenticator.
+     * 
+     * @param authenticationMethod authentication method
+     * @param rule authority rule
+     * @return created authenticator
+     */
+    @SneakyThrows(ReflectiveOperationException.class)
+    public static PostgreSQLAuthenticator createAuthenticator(final String 
authenticationMethod, final AuthorityRule rule) {
+        PostgreSQLAuthenticatorFactory factory = 
findAuthenticatorFactory(getAuthenticator(authenticationMethod));
+        try {
+            return factory.authenticatorClass.getConstructor().newInstance();
+        } catch (final NoSuchMethodException ignored) {
+            return 
factory.authenticatorClass.getConstructor(AuthorityRule.class).newInstance(rule);
+        }
+    }
+    
+    private static PostgreSQLAuthenticationMethod getAuthenticator(final 
String authenticationMethod) {
+        try {
+            return 
PostgreSQLAuthenticationMethod.valueOf(authenticationMethod.toUpperCase());
+        } catch (final IllegalArgumentException ignored) {
+            return getDefaultAuthenticatorFactory().authenticationMethod;
+        }
+    }
+    
+    private static PostgreSQLAuthenticatorFactory 
findAuthenticatorFactory(final PostgreSQLAuthenticationMethod 
authenticationMethod) {
+        Optional<PostgreSQLAuthenticatorFactory> matchedFactory = 
Arrays.stream(PostgreSQLAuthenticatorFactory.values()).filter(each -> 
each.authenticationMethod == authenticationMethod).findAny();
+        return 
matchedFactory.orElseGet(PostgreSQLAuthenticatorFactory::getDefaultAuthenticatorFactory);
+    }
+    
+    private static PostgreSQLAuthenticatorFactory 
getDefaultAuthenticatorFactory() {
+        Optional<PostgreSQLAuthenticatorFactory> defaultFactory = 
Arrays.stream(PostgreSQLAuthenticatorFactory.values()).filter(each -> 
each.isDefault).findAny();
+        return defaultFactory.orElseThrow(IllegalArgumentException::new);
+    }
+}

Reply via email to