Skip to content

Commit a25b21f

Browse files
authored
Support basic auth (#14644)
* Support basic auth * Fix sd * Use trie * Fix ut * Fix ut * Fix ut
1 parent 0129990 commit a25b21f

File tree

23 files changed

+510
-158
lines changed

23 files changed

+510
-158
lines changed

dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,21 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
206206
*/
207207
private Boolean auth;
208208

209+
/**
210+
* Authenticator for authentication
211+
*/
212+
private String authenticator;
213+
214+
/**
215+
* Username for basic authenticator
216+
*/
217+
private String username;
218+
219+
/**
220+
* Password for basic authenticator
221+
*/
222+
private String password;
223+
209224
/**
210225
* Use separate instances for services with the same serviceKey (applies when using ReferenceConfig and SimpleReferenceCache together).
211226
* Directly calling ReferenceConfig.get() will not check this attribute.
@@ -892,6 +907,33 @@ public void setAuth(Boolean auth) {
892907
this.auth = auth;
893908
}
894909

910+
public String getAuthenticator() {
911+
return authenticator;
912+
}
913+
914+
public AbstractInterfaceConfig setAuthenticator(String authenticator) {
915+
this.authenticator = authenticator;
916+
return this;
917+
}
918+
919+
public String getUsername() {
920+
return username;
921+
}
922+
923+
public AbstractInterfaceConfig setUsername(String username) {
924+
this.username = username;
925+
return this;
926+
}
927+
928+
public String getPassword() {
929+
return password;
930+
}
931+
932+
public AbstractInterfaceConfig setPassword(String password) {
933+
this.password = password;
934+
return this;
935+
}
936+
895937
public SslConfig getSslConfig() {
896938
return getConfigManager().getSsl().orElse(null);
897939
}

dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@
2626
import org.apache.dubbo.common.constants.CommonConstants;
2727
import org.apache.dubbo.common.utils.StringUtils;
2828
import org.apache.dubbo.rpc.Invocation;
29-
import org.apache.dubbo.rpc.model.ApplicationModel;
29+
import org.apache.dubbo.rpc.model.FrameworkModel;
3030
import org.apache.dubbo.rpc.support.RpcUtils;
3131

3232
public class AccessKeyAuthenticator implements Authenticator {
33-
private final ApplicationModel applicationModel;
33+
private final FrameworkModel frameworkModel;
3434

35-
public AccessKeyAuthenticator(ApplicationModel applicationModel) {
36-
this.applicationModel = applicationModel;
35+
public AccessKeyAuthenticator(FrameworkModel frameworkModel) {
36+
this.frameworkModel = frameworkModel;
3737
}
3838

3939
@Override
@@ -73,7 +73,7 @@ public void authenticate(Invocation invocation, URL url) throws RpcAuthenticatio
7373
}
7474

7575
AccessKeyPair getAccessKeyPair(Invocation invocation, URL url) {
76-
AccessKeyStorage accessKeyStorage = applicationModel
76+
AccessKeyStorage accessKeyStorage = frameworkModel
7777
.getExtensionLoader(AccessKeyStorage.class)
7878
.getExtension(url.getParameter(Constants.ACCESS_KEY_STORAGE_KEY, Constants.DEFAULT_ACCESS_KEY_STORAGE));
7979

@@ -97,10 +97,6 @@ String getSignature(URL url, Invocation invocation, String secretKey, String tim
9797
RpcUtils.getMethodName(invocation),
9898
secretKey,
9999
time);
100-
boolean parameterEncrypt = url.getParameter(Constants.PARAMETER_SIGNATURE_ENABLE_KEY, false);
101-
if (parameterEncrypt) {
102-
return SignatureUtils.sign(invocation.getArguments(), requestString, secretKey);
103-
}
104100
return SignatureUtils.sign(requestString, secretKey);
105101
}
106102
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.auth;
18+
19+
import org.apache.dubbo.auth.exception.RpcAuthenticationException;
20+
import org.apache.dubbo.auth.spi.Authenticator;
21+
import org.apache.dubbo.common.URL;
22+
import org.apache.dubbo.rpc.Invocation;
23+
24+
import java.util.Base64;
25+
import java.util.Objects;
26+
27+
public class BasicAuthenticator implements Authenticator {
28+
29+
@Override
30+
public void sign(Invocation invocation, URL url) {
31+
String username = url.getParameter(Constants.USERNAME_KEY);
32+
String password = url.getParameter(Constants.PASSWORD_KEY);
33+
String auth = username + ":" + password;
34+
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
35+
String authHeaderValue = "Basic " + encodedAuth;
36+
37+
invocation.setAttachment(Constants.AUTHORIZATION_HEADER_LOWER, authHeaderValue);
38+
}
39+
40+
@Override
41+
public void authenticate(Invocation invocation, URL url) throws RpcAuthenticationException {
42+
String username = url.getParameter(Constants.USERNAME_KEY);
43+
String password = url.getParameter(Constants.PASSWORD_KEY);
44+
String auth = username + ":" + password;
45+
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
46+
String authHeaderValue = "Basic " + encodedAuth;
47+
48+
if (!Objects.equals(authHeaderValue, invocation.getAttachment(Constants.AUTHORIZATION_HEADER))
49+
&& !Objects.equals(authHeaderValue, invocation.getAttachment(Constants.AUTHORIZATION_HEADER_LOWER))) {
50+
throw new RpcAuthenticationException("Failed to authenticate, maybe consumer side did not enable the auth");
51+
}
52+
}
53+
}

dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/Constants.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818

1919
public interface Constants {
2020

21-
String SERVICE_AUTH = "auth";
21+
String AUTH_KEY = "auth";
2222

23-
String AUTHENTICATOR = "authenticator";
23+
String AUTHENTICATOR_KEY = "authenticator";
2424

25-
String DEFAULT_AUTHENTICATOR = "accesskey";
25+
String USERNAME_KEY = "username";
26+
27+
String PASSWORD_KEY = "password";
28+
29+
String DEFAULT_AUTHENTICATOR = "basic";
2630

2731
String DEFAULT_ACCESS_KEY_STORAGE = "urlstorage";
2832

@@ -41,4 +45,11 @@ public interface Constants {
4145
String SIGNATURE_STRING_FORMAT = "%s#%s#%s#%s";
4246

4347
String PARAMETER_SIGNATURE_ENABLE_KEY = "param.sign";
48+
49+
String AUTH_SUCCESS = "auth.success";
50+
51+
String AUTHORIZATION_HEADER_LOWER = "authorization";
52+
53+
String AUTHORIZATION_HEADER = "Authorization";
54+
String REMOTE_ADDRESS_KEY = "tri.remote.address";
4455
}

dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,29 @@
2626
import org.apache.dubbo.rpc.Invoker;
2727
import org.apache.dubbo.rpc.Result;
2828
import org.apache.dubbo.rpc.RpcException;
29-
import org.apache.dubbo.rpc.model.ApplicationModel;
29+
import org.apache.dubbo.rpc.model.FrameworkModel;
3030

3131
/**
3232
* The ConsumerSignFilter
3333
*
3434
* @see org.apache.dubbo.rpc.Filter
3535
*/
36-
@Activate(group = CommonConstants.CONSUMER, value = Constants.SERVICE_AUTH, order = -10000)
36+
@Activate(group = CommonConstants.CONSUMER, value = Constants.AUTH_KEY, order = -10000)
3737
public class ConsumerSignFilter implements Filter {
38-
private final ApplicationModel applicationModel;
38+
private final FrameworkModel frameworkModel;
3939

40-
public ConsumerSignFilter(ApplicationModel applicationModel) {
41-
this.applicationModel = applicationModel;
40+
public ConsumerSignFilter(FrameworkModel frameworkModel) {
41+
this.frameworkModel = frameworkModel;
4242
}
4343

4444
@Override
4545
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
4646
URL url = invoker.getUrl();
47-
boolean shouldAuth = url.getParameter(Constants.SERVICE_AUTH, false);
47+
boolean shouldAuth = url.getParameter(Constants.AUTH_KEY, false);
4848
if (shouldAuth) {
49-
Authenticator authenticator = applicationModel
49+
Authenticator authenticator = frameworkModel
5050
.getExtensionLoader(Authenticator.class)
51-
.getExtension(url.getParameter(Constants.AUTHENTICATOR, Constants.DEFAULT_AUTHENTICATOR));
51+
.getExtension(url.getParameter(Constants.AUTHENTICATOR_KEY, Constants.DEFAULT_AUTHENTICATOR));
5252
authenticator.sign(invocation, url);
5353
}
5454
return invoker.invoke(invocation);

dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,27 @@
2727
import org.apache.dubbo.rpc.Invoker;
2828
import org.apache.dubbo.rpc.Result;
2929
import org.apache.dubbo.rpc.RpcException;
30-
import org.apache.dubbo.rpc.model.ApplicationModel;
30+
import org.apache.dubbo.rpc.model.FrameworkModel;
3131

32-
@Activate(group = CommonConstants.PROVIDER, value = Constants.SERVICE_AUTH, order = -10000)
32+
@Activate(group = CommonConstants.PROVIDER, value = Constants.AUTH_KEY, order = -10000)
3333
public class ProviderAuthFilter implements Filter {
34-
private final ApplicationModel applicationModel;
34+
private final FrameworkModel frameworkModel;
3535

36-
public ProviderAuthFilter(ApplicationModel applicationModel) {
37-
this.applicationModel = applicationModel;
36+
public ProviderAuthFilter(FrameworkModel frameworkModel) {
37+
this.frameworkModel = frameworkModel;
3838
}
3939

4040
@Override
4141
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
4242
URL url = invoker.getUrl();
43-
boolean shouldAuth = url.getParameter(Constants.SERVICE_AUTH, false);
43+
boolean shouldAuth = url.getParameter(Constants.AUTH_KEY, false);
4444
if (shouldAuth) {
45-
Authenticator authenticator = applicationModel
45+
if (Boolean.TRUE.equals(invocation.getAttributes().get(Constants.AUTH_SUCCESS))) {
46+
return invoker.invoke(invocation);
47+
}
48+
Authenticator authenticator = frameworkModel
4649
.getExtensionLoader(Authenticator.class)
47-
.getExtension(url.getParameter(Constants.AUTHENTICATOR, Constants.DEFAULT_AUTHENTICATOR));
50+
.getExtension(url.getParameter(Constants.AUTHENTICATOR_KEY, Constants.DEFAULT_AUTHENTICATOR));
4851
try {
4952
authenticator.authenticate(invocation, url);
5053
} catch (Exception e) {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.auth.filter;
18+
19+
import org.apache.dubbo.auth.Constants;
20+
import org.apache.dubbo.auth.spi.Authenticator;
21+
import org.apache.dubbo.common.URL;
22+
import org.apache.dubbo.common.extension.Activate;
23+
import org.apache.dubbo.rpc.HeaderFilter;
24+
import org.apache.dubbo.rpc.Invoker;
25+
import org.apache.dubbo.rpc.RpcContext;
26+
import org.apache.dubbo.rpc.RpcException;
27+
import org.apache.dubbo.rpc.RpcInvocation;
28+
import org.apache.dubbo.rpc.model.FrameworkModel;
29+
import org.apache.dubbo.rpc.support.RpcUtils;
30+
31+
import static org.apache.dubbo.rpc.RpcException.AUTHORIZATION_EXCEPTION;
32+
33+
@Activate(value = Constants.AUTH_KEY, order = -20000)
34+
public class ProviderAuthHeaderFilter implements HeaderFilter {
35+
private final FrameworkModel frameworkModel;
36+
37+
public ProviderAuthHeaderFilter(FrameworkModel frameworkModel) {
38+
this.frameworkModel = frameworkModel;
39+
}
40+
41+
@Override
42+
public RpcInvocation invoke(Invoker<?> invoker, RpcInvocation invocation) throws RpcException {
43+
URL url = invoker.getUrl();
44+
boolean shouldAuth = url.getParameter(Constants.AUTH_KEY, false);
45+
if (shouldAuth) {
46+
Authenticator authenticator = frameworkModel
47+
.getExtensionLoader(Authenticator.class)
48+
.getExtension(url.getParameter(Constants.AUTHENTICATOR_KEY, Constants.DEFAULT_AUTHENTICATOR));
49+
try {
50+
authenticator.authenticate(invocation, url);
51+
} catch (Exception e) {
52+
Class<?> serviceType = invoker.getInterface();
53+
throw new RpcException(
54+
AUTHORIZATION_EXCEPTION,
55+
"Forbid invoke remote service " + serviceType + " method " + RpcUtils.getMethodName(invocation)
56+
+ "() from consumer "
57+
+ invocation.getAttributes().get(Constants.REMOTE_ADDRESS_KEY) + " to provider "
58+
+ RpcContext.getServiceContext().getLocalHost());
59+
}
60+
invocation.getAttributes().put(Constants.AUTH_SUCCESS, Boolean.TRUE);
61+
}
62+
return invocation;
63+
}
64+
}

dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/AccessKeyStorage.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818

1919
import org.apache.dubbo.auth.model.AccessKeyPair;
2020
import org.apache.dubbo.common.URL;
21+
import org.apache.dubbo.common.extension.ExtensionScope;
2122
import org.apache.dubbo.common.extension.SPI;
2223
import org.apache.dubbo.rpc.Invocation;
2324

2425
/**
2526
* This SPI Extension support us to store our {@link AccessKeyPair} or load {@link AccessKeyPair} from other
2627
* storage, such as filesystem.
2728
*/
28-
@SPI
29+
@SPI(scope = ExtensionScope.FRAMEWORK)
2930
public interface AccessKeyStorage {
3031

3132
/**

dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/spi/Authenticator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818

1919
import org.apache.dubbo.auth.exception.RpcAuthenticationException;
2020
import org.apache.dubbo.common.URL;
21+
import org.apache.dubbo.common.extension.ExtensionScope;
2122
import org.apache.dubbo.common.extension.SPI;
2223
import org.apache.dubbo.rpc.Invocation;
2324

24-
@SPI("accessKey")
25+
@SPI(scope = ExtensionScope.FRAMEWORK, value = "basic")
2526
public interface Authenticator {
2627

2728
/**
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
accesskey=org.apache.dubbo.auth.AccessKeyAuthenticator
1+
accesskey=org.apache.dubbo.auth.AccessKeyAuthenticator
2+
basic=org.apache.dubbo.auth.BasicAuthenticator

0 commit comments

Comments
 (0)