英文:
Unable to authenticate Kusto Client using JWTToken
问题
我们使用Java 8
和msal4j
版本0.6.0-preview
。要连接到 Kusto,我们使用 JWT 令牌:
ConnectionStringBuilder csb = ConnectionStringBuilder.createWithAadAccessTokenAuthentication(resourceUri, accessToken);
Client kustoClient = ClientFactory.createClient(csb);
在createWithAadAccessTokenAuthentication()
内部,它调用了这个ConnectionStringBuilder
构造函数:
public static ConnectionStringBuilder createWithAadAccessTokenAuthentication(String resourceUri, String token) {
if (StringUtils.isEmpty(resourceUri)) {
throw new IllegalArgumentException("resourceUri cannot be null or empty");
} else if (StringUtils.isEmpty(token)) {
throw new IllegalArgumentException("token cannot be null or empty");
} else {
ConnectionStringBuilder csb = new ConnectionStringBuilder(resourceUri);
csb.accessToken = token;
return csb;
}
}
它将除了clusterUri
之外的每个字段都设置为null
。
private ConnectionStringBuilder(String resourceUri) {
this.clusterUri = resourceUri;
this.usernameHint = null;
this.applicationClientId = null;
this.applicationKey = null;
this.aadAuthorityId = null;
this.x509Certificate = null;
this.privateKey = null;
this.accessToken = null;
this.tokenProvider = null;
}
因此,我们从createClient()
方法中得到了一个错误。因为它调用了ClientImpl(csb)
。host
和auth
返回null
,这会触发这一行的空指针异常:String auth = clusterUri.getAuthority().toLowerCase();
public static Client createClient(ConnectionStringBuilder csb) throws URISyntaxException {
return new ClientImpl(csb);
}
public ClientImpl(ConnectionStringBuilder csb) throws URISyntaxException {
String url = csb.getClusterUrl();
URI clusterUri = new URI(url);
String host = clusterUri.getHost();
String auth = clusterUri.getAuthority().toLowerCase();
if (host == null && auth.endsWith(";fed=true")) {
url = (new URIBuilder()).setScheme(clusterUri.getScheme()).setHost(auth.substring(0, clusterUri.getAuthority().indexOf(";fed=true"))).toString();
csb.setClusterUrl(url);
}
this.clusterUrl = url;
this.aadAuthenticationHelper = TokenProviderFactory.createTokenProvider(csb);
this.clientVersionForTracing = "Kusto.Java.Client";
String version = Utils.getPackageVersion();
if (StringUtils.isNotBlank(version)) {
this.clientVersionForTracing = this.clientVersionForTracing + ":" + version;
}
if StringUtils.isNotBlank(csb.getClientVersionForTracing())) {
this.clientVersionForTracing = this.clientVersionForTracing + "[" + csb.getClientVersionForTracing() + "]";
}
this.applicationNameForTracing = csb.getApplicationNameForTracing();
}
这里有什么其他的替代方案?
英文:
We use Java 8
and msal4j
version 0.6.0-preview
. To connect to Kusto, we use JWT Token:
ConnectionStringBuilder csb = ConnectionStringBuilder.createWithAadAccessTokenAuthentication(resourceUri, accessToken);
Client kustoClient = ClientFactory.createClient(csb);
Inside thencreateWithAadAccessTokenAuthentication()
, it is calling this ConnectionStringBuilder
constructor:
public static ConnectionStringBuilder createWithAadAccessTokenAuthentication(String resourceUri, String token) {
if (StringUtils.isEmpty(resourceUri)) {
throw new IllegalArgumentException("resourceUri cannot be null or empty");
} else if (StringUtils.isEmpty(token)) {
throw new IllegalArgumentException("token cannot be null or empty");
} else {
ConnectionStringBuilder csb = new ConnectionStringBuilder(resourceUri);
csb.accessToken = token;
return csb;
}
}
it is setting every field to null
except for clusterUri
.
private ConnectionStringBuilder(String resourceUri) {
this.clusterUri = resourceUri;
this.usernameHint = null;
this.applicationClientId = null;
this.applicationKey = null;
this.aadAuthorityId = null;
this.x509Certificate = null;
this.privateKey = null;
this.accessToken = null;
this.tokenProvider = null;
}
Thus we got an error from createClient()
method. Because it is calling ClientImpl(csb)
. host
and auth
are returning null, which triggers null pointer exception in this line: String auth = clusterUri.getAuthority().toLowerCase();
public static Client createClient(ConnectionStringBuilder csb) throws URISyntaxException {
return new ClientImpl(csb);
}
public ClientImpl(ConnectionStringBuilder csb) throws URISyntaxException {
String url = csb.getClusterUrl();
URI clusterUri = new URI(url);
String host = clusterUri.getHost();
String auth = clusterUri.getAuthority().toLowerCase();
if (host == null && auth.endsWith(";fed=true")) {
url = (new URIBuilder()).setScheme(clusterUri.getScheme()).setHost(auth.substring(0, clusterUri.getAuthority().indexOf(";fed=true"))).toString();
csb.setClusterUrl(url);
}
this.clusterUrl = url;
this.aadAuthenticationHelper = TokenProviderFactory.createTokenProvider(csb);
this.clientVersionForTracing = "Kusto.Java.Client";
String version = Utils.getPackageVersion();
if (StringUtils.isNotBlank(version)) {
this.clientVersionForTracing = this.clientVersionForTracing + ":" + version;
}
if (StringUtils.isNotBlank(csb.getClientVersionForTracing())) {
this.clientVersionForTracing = this.clientVersionForTracing + "[" + csb.getClientVersionForTracing() + "]";
}
this.applicationNameForTracing = csb.getApplicationNameForTracing();
}
What are the other alternatives here?
答案1
得分: 1
你正在使用哪个版本的Kusto SDK?
您是否可以使用SDK自身提供的其他AuthN选项,而不是手动获取令牌并将其值传递给SDK?
通常更推荐这种做法(更不容易因令牌过期而导致长时间运行的错误)。
附言:通常在源代码的存储库中报告此类问题是常见的。
https://github.com/Azure/azure-kusto-java/issues
英文:
Which version of the Kusto SDK are you using?
Can you use any of the other AuthN options provided by the SDK itself, instead of acquiring the token manually and passing it's value to the SDK?
It's generally more recommanded (less prone to long running errors due to token expiration)
P.S. It common to report such issues in the repo for the source code.
https://github.com/Azure/azure-kusto-java/issues
答案2
得分: 1
我们在面对面交谈后发现问题出在resourceUri参数中传递的值,而这个参数期望的是集群的URL("https://cluster.region.kusto.windows.net"),而提供的URI是ARM资源的URI,因此在调用new URI()时未解析URL的主机和身份验证部分。
英文:
After talking F2F we found the issue is with the value passed in the resourceUri param, while this expects a url of the cluster ("https://cluster.region.kusto.windows.net") the provided uri was the ARM resource uri hence no host and no auth sections of the URL were parsed by the call to new URI().
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论