Skip to content

Commit

Permalink
refact(auth): cache login role in auth client to avoid sending rpc re…
Browse files Browse the repository at this point in the history
…peatedly

TODO: also need be compatible with token way (consider put 'usrname + passwd' together into caches's key)
  • Loading branch information
imbajin committed Jun 17, 2021
1 parent bc9a5a8 commit e6452b5
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@

import java.io.Console;
import java.net.InetAddress;
import java.time.Duration;
import java.util.Scanner;

import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang.StringUtils;
import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;

import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.backend.cache.Cache;
import com.baidu.hugegraph.backend.cache.CacheManager;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.config.CoreOptions;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
Expand All @@ -38,8 +43,10 @@
public class StandardAuthenticator implements HugeAuthenticator {

private static final String INITING_STORE = "initing_store";
private static final long CACHE_EXPIRE = Duration.ofMinutes(10L).toMillis();

private HugeGraph graph = null;
private Cache<Id, UserRoleCache> usersRoleCache;

private HugeGraph graph() {
E.checkState(this.graph != null, "Must setup Authenticator first");
Expand All @@ -48,11 +55,10 @@ private HugeGraph graph() {

private void initAdminUser() throws Exception {
this.initAdminUser(this.inputPassword());

this.graph.close();
}

public void initAdminUser(String password) throws Exception {
public void initAdminUser(String password) {
// Not allowed to call by non main thread
String caller = Thread.currentThread().getName();
E.checkState(caller.equals("main"), "Invalid caller '%s'", caller);
Expand Down Expand Up @@ -95,7 +101,12 @@ public void setup(HugeConfig config) {
String graphName = config.get(ServerOptions.AUTH_GRAPH_STORE);
String graphPath = config.getMap(ServerOptions.GRAPHS).get(graphName);
E.checkArgument(graphPath != null,
"Invalid graph name '%s'", graphName);
"Can't find graph name '%s' in config '%s' at " +
"'rest-server.properties' to store auth information, " +
"please ensure the value of '%s' matches it correctly",
graphName, ServerOptions.GRAPHS,
ServerOptions.AUTH_GRAPH_STORE.name());

HugeConfig graphConfig = new HugeConfig(graphPath);
if (config.getProperty(INITING_STORE) != null &&
config.getBoolean(INITING_STORE)) {
Expand All @@ -110,12 +121,14 @@ public void setup(HugeConfig config) {
new RpcClientProviderWithAuth(config);
this.graph.switchAuthManager(clientProvider.authManager());
}

this.usersRoleCache = this.cache("users_role");
}

/**
* Verify if a user is legal
* @param username the username for authentication
* @param password the password for authentication
* @param username the username for authentication
* @param password the password for authentication
* @return String No permission if return ROLE_NONE else return a role
*/
@Override
Expand All @@ -125,8 +138,19 @@ public RolePermission authenticate(String username, String password) {
E.checkArgumentNotNull(password,
"The password parameter can't be null");

RolePermission role = this.graph().authManager().loginUser(username,
password);
// TODO: Be compatible with JWT(token) way
Id usrname = IdGenerator.of(username);
UserRoleCache userRole = this.usersRoleCache.getOrFetch(usrname, r -> {
RolePermission rolePermission = this.graph().authManager()
.loginUser(username, password);
return new UserRoleCache(rolePermission, password);
});

RolePermission role = null;
if (userRole.passwd().equals(password)) {
role = userRole.role();
}

if (role == null) {
role = ROLE_NONE;
} else if (username.equals(USER_ADMIN)) {
Expand All @@ -135,6 +159,33 @@ public RolePermission authenticate(String username, String password) {
return role;
}

class UserRoleCache {

private RolePermission role;
private String passwd;

public UserRoleCache(RolePermission role, String passwd) {
this.role = role;
this.passwd = passwd;
}

public String passwd() {
return passwd;
}

public void setPasswd(String passwd) {
this.passwd = passwd;
}

public RolePermission role() {
return role;
}

public void setRole(RolePermission role) {
this.role = role;
}
}

@Override
public AuthManager authManager() {
return this.graph().authManager();
Expand All @@ -145,6 +196,13 @@ public SaslNegotiator newSaslNegotiator(InetAddress remoteAddress) {
throw new NotImplementedException("SaslNegotiator is unsupported");
}

private <V> Cache<Id, V> cache(String prefix) {
String name = prefix + "-" + this.graph.name();
Cache<Id, V> cache = CacheManager.instance().cache(name);
cache.expire(CACHE_EXPIRE);
return cache;
}

public static void initAdminUserIfNeeded(String confFile) throws Exception {
StandardAuthenticator auth = new StandardAuthenticator();
HugeConfig config = new HugeConfig(confFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ public static synchronized ServerOptions instance() {
public static final ConfigOption<Integer> MAX_WORKER_THREADS =
new ConfigOption<>(
"restserver.max_worker_threads",
"The maxmium worker threads of rest server.",
"The maximum worker threads of rest server.",
rangeInt(2, Integer.MAX_VALUE),
2 * CoreOptions.CPUS
);

public static final ConfigOption<Integer> MIN_FREE_MEMORY =
new ConfigOption<>(
"restserver.min_free_memory",
"The minmium free memory(MB) of rest server, requests " +
"The minimum free memory(MB) of rest server, requests " +
"will be rejected when the available memory of system " +
"is lower than this value.",
nonNegativeInt(),
Expand Down Expand Up @@ -188,7 +188,7 @@ public static synchronized ServerOptions instance() {
public static final ConfigOption<String> AUTHENTICATOR =
new ConfigOption<>(
"auth.authenticator",
"The class path of authenticator implemention. " +
"The class path of authenticator implementation. " +
"e.g., com.baidu.hugegraph.auth.StandardAuthenticator, " +
"or com.baidu.hugegraph.auth.ConfigAuthenticator.",
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public interface Cache<K, V> {
public static final String ACTION_INVALIDED = "invalided";
public static final String ACTION_CLEARED = "cleared";

public Object get(K id);
public V get(K id);

public Object getOrFetch(K id, Function<K, V> fetcher);
public V getOrFetch(K id, Function<K, V> fetcher);

public boolean containsKey(K id);

Expand Down

0 comments on commit e6452b5

Please sign in to comment.