Skip to content
This repository was archived by the owner on Mar 12, 2026. It is now read-only.

Commit e02eb53

Browse files
authored
feat: add basic auth (#78)
1 parent 96537df commit e02eb53

5 files changed

Lines changed: 96 additions & 0 deletions

File tree

horaedb-grpc/src/main/java/org/apache/horaedb/rpc/GrpcClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import io.grpc.stub.ClientCalls;
3636
import io.grpc.stub.StreamObserver;
3737

38+
import org.apache.horaedb.rpc.interceptors.AuthenticationInterceptor;
3839
import org.slf4j.Logger;
3940
import org.slf4j.LoggerFactory;
4041

@@ -394,6 +395,8 @@ public void addInterceptor(final ClientInterceptor interceptor) {
394395
// Interceptors run in the reverse order in which they are added
395396
private void initInterceptors() {
396397
// the last one
398+
addInterceptor(new AuthenticationInterceptor(opts.getUser(), opts.getPassword()));
399+
397400
addInterceptor(new MetricInterceptor());
398401

399402
// the second
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2023 CeresDB Project Authors. Licensed under Apache-2.0.
3+
*/
4+
package org.apache.horaedb.rpc.interceptors;
5+
6+
import io.grpc.*;
7+
8+
import java.util.Base64;
9+
10+
public class AuthenticationInterceptor implements ClientInterceptor {
11+
private final String token;
12+
13+
public AuthenticationInterceptor(String user, String password) {
14+
// Build token
15+
this.token = Base64.getEncoder().encodeToString((user + ":" + password).getBytes());
16+
}
17+
18+
@Override
19+
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method,
20+
final CallOptions callOpts, Channel next) {
21+
22+
return new AuthenticationAttachingClientCall<>(next.newCall(method, callOpts), token);
23+
}
24+
25+
private static final class AuthenticationAttachingClientCall<ReqT, RespT>
26+
extends ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT> {
27+
28+
private final String token;
29+
private static final String AUTHORIZATION_HEADER = "authorization";
30+
private static final String BASIC_PREFIX = "Basic ";
31+
32+
private AuthenticationAttachingClientCall(ClientCall<ReqT, RespT> delegate, String token) {
33+
super(delegate);
34+
this.token = token;
35+
}
36+
37+
@Override
38+
public void start(Listener<RespT> responseListener, Metadata headers) {
39+
headers.put(Metadata.Key.of(AUTHORIZATION_HEADER, Metadata.ASCII_STRING_MARSHALLER), BASIC_PREFIX + token);
40+
super.start(responseListener, headers);
41+
}
42+
}
43+
44+
}

horaedb-protocol/src/main/java/org/apache/horaedb/options/HoraeDBOptions.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ public static final class Builder {
166166
// The routeMode for sdk, only Proxy and Direct support now.
167167
private RouteMode routeMode;
168168
private String database;
169+
private String user;
170+
private String password;
171+
169172
// Asynchronous thread pool, which is used to handle various asynchronous tasks in the SDK.
170173
private Executor asyncWritePool;
171174
private Executor asyncReadPool;
@@ -201,6 +204,13 @@ public Builder(Endpoint clusterAddress, RouteMode routeMode) {
201204
this.routeMode = routeMode;
202205
}
203206

207+
@SuppressWarnings("PMD")
208+
public Builder authentication(final String user, final String password) {
209+
this.user = user;
210+
this.password = password;
211+
return this;
212+
}
213+
204214
/**
205215
*
206216
* @param database the database name
@@ -366,6 +376,10 @@ public HoraeDBOptions build() {
366376
opts.asyncWritePool = asyncWritePool;
367377
opts.asyncReadPool = asyncReadPool;
368378
opts.rpcOptions = this.rpcOptions;
379+
380+
opts.rpcOptions.setUser(this.user);
381+
opts.rpcOptions.setPassword(this.password);
382+
369383
opts.routerOptions = new RouterOptions();
370384
opts.routerOptions.setClusterAddress(this.clusterAddress);
371385
opts.routerOptions.setMaxCachedSize(this.routeTableMaxCachedSize);

horaedb-rpc/src/main/java/org/apache/horaedb/rpc/RpcOptions.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
*/
1515
public class RpcOptions implements Copiable<RpcOptions> {
1616

17+
/**
18+
* Username provided for authentication
19+
*/
20+
private String user;
21+
22+
/**
23+
* Password provided for authentication
24+
*/
25+
private String password;
26+
1727
/**
1828
* RPC request default timeout in milliseconds
1929
* Default: 10000(10s)
@@ -96,6 +106,14 @@ public class RpcOptions implements Copiable<RpcOptions> {
96106
*/
97107
private long connectionMaxAgeMs = 0;
98108

109+
public String getUser() {
110+
return user;
111+
}
112+
113+
public String getPassword() {
114+
return password;
115+
}
116+
99117
public int getDefaultRpcTimeout() {
100118
return defaultRpcTimeout;
101119
}
@@ -180,6 +198,14 @@ public LimitKind getLimitKind() {
180198
return limitKind;
181199
}
182200

201+
public void setUser(String user) {
202+
this.user = user;
203+
}
204+
205+
public void setPassword(String password) {
206+
this.password = password;
207+
}
208+
183209
public void setLimitKind(LimitKind limitKind) {
184210
this.limitKind = limitKind;
185211
}
@@ -235,6 +261,8 @@ public void setLogOnLimitChange(boolean logOnLimitChange) {
235261
@Override
236262
public RpcOptions copy() {
237263
final RpcOptions opts = new RpcOptions();
264+
opts.user = this.user;
265+
opts.password = this.password;
238266
opts.defaultRpcTimeout = this.defaultRpcTimeout;
239267
opts.rpcThreadPoolSize = this.rpcThreadPoolSize;
240268
opts.rpcThreadPoolQueueSize = this.rpcThreadPoolQueueSize;

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,13 @@
400400
<exclude>**/sql/TokenMgrException.java</exclude>
401401
</excludes>
402402
</configuration>
403+
<dependencies>
404+
<dependency>
405+
<groupId>org.ow2.asm</groupId>
406+
<artifactId>asm</artifactId>
407+
<version>9.2</version>
408+
</dependency>
409+
</dependencies>
403410
</plugin>
404411
<plugin>
405412
<groupId>com.mycila</groupId>

0 commit comments

Comments
 (0)