问题描述

使用中国区的Azure,在获取Token时候,参考了 adal4j的代码,在官方文档中,发现了如下的片段代码:

ExecutorService service = Executors.newFixedThreadPool(1);
AuthenticationContext context = new AuthenticationContext(AUTHORITY, false, service);
Future<AuthenticationResult> future = context.acquireToken(
"https://graph.windows.net", YOUR_TENANT_ID, username, password,
null);
AuthenticationResult result = future.get();
System.out.println("Access Token - " + result.getAccessToken());
System.out.println("Refresh Token - " + result.getRefreshToken());
System.out.println("ID Token - " + result.getIdToken());

以上代码中,有一些参数很不明确:

1)AUTHORITY, 是什么意思呢?

2)acquireTokne方法中的 https://graph.windows.net 是指向global azure的资源,如果是中国区azure的资源,那么resource url是多少呢?

3)YOUR_TENANT_ID,它的值是什么呢?

问题解答

第一个问题:AUTHORITY, 是什么意思,它的值是什么呢?

AUTHORITY,表示认证的主体,它是一个URL,表示可以从该主体中获取到认证Token。 它的格式为:https://<authority host>/<tenant id> ,所以在使用Azure的过程中,根据Azure环境的不同,Host 有以下四个值。

  1. AzureChina :The host of the Azure Active Directory authority for tenants in the Azure China Cloud.  AZURE_CHINA = "login.chinacloudapi.cn"
  2. AzureGermany: The host of the Azure Active Directory authority for tenants in the Azure German Cloud.  AZURE_GERMANY = "login.microsoftonline.de"
  3. AzureGovernment: The host of the Azure Active Directory authority for tenants in the Azure US Government Cloud.  AZURE_GOVERNMENT = "login.microsoftonline.us"
  4. AzurePublicCloud: The host of the Azure Active Directory authority for tenants in the Azure Public Cloud. AZURE_PUBLIC_CLOUD = "login.microsoftonline.com"

所以,这里我们需要使用的值为:String AUTHORITY = "https://login.chinacloudapi.cn/<tenant id >";

那么如何来获取Tenant ID呢?

登录到Azure门户 --> 进入AAD中,在Overview页面查看Tenant ID (https://portal.azure.cn/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview)

第二个问题:acquireTokne方法中的 https://graph.windows.net 是指向global azure的资源,如果是中国区azure的资源,那么resource url是多少呢?

根据中国区Azure的开发文档,并没有查找到对应于 graph.windows.net的中国区Graph 终结点。但是,中国区Graph 的终结点为:microsoftgraph.chinacloudapi.cn,所以,以上示例中应该使用的值应是:

https://microsoftgraph.chinacloudapi.cn/

第三个问题:YOUR_TENANT_ID,它的值是什么呢?

在对比了adal4j的源代码后,在acquireToken方法定义中,发现YOUR_TENANT_ID所对应的值应该是 clientId ()。所以,官网参考文档中的YOUR_TENANT_ID存在误导情景。需要修改为YOUR_CLIENT_ID。

ADAL4J中acquireToken源码(acquireToken有多个重载,但此处只列举出代码中使用的这个重载)

    /**
* Acquires a security token from the authority using a Refresh Token
* previously received.
*
* @param clientId
* Name or ID of the client requesting the token.
* @param resource
* Identifier of the target resource that is the recipient of the
* requested token. If null, token is requested for the same
* resource refresh token was originally issued for. If passed,
* resource should match the original resource used to acquire
* refresh token unless token service supports refresh token for
* multiple resources.
* @param username
* Username of the managed or federated user.
* @param password
* Password of the managed or federated user.
* @param callback
* optional callback object for non-blocking execution.
* @return A {@link Future} object representing the
* {@link AuthenticationResult} of the call. It contains Access
* Token, Refresh Token and the Access Token's expiration time.
*/
public Future<AuthenticationResult> acquireToken(final String resource,
final String clientId, final String username,
final String password, final AuthenticationCallback callback) {
if (StringHelper.isBlank(resource)) {
throw new IllegalArgumentException("resource is null or empty");
} if (StringHelper.isBlank(clientId)) {
throw new IllegalArgumentException("clientId is null or empty");
} if (StringHelper.isBlank(username)) {
throw new IllegalArgumentException("username is null or empty");
} if (StringHelper.isBlank(password)) {
throw new IllegalArgumentException("password is null or empty");
} return this.acquireToken(new AdalAuthorizatonGrant(
new ResourceOwnerPasswordCredentialsGrant(username, new Secret(
password)), resource), new ClientAuthenticationPost(
ClientAuthenticationMethod.NONE, new ClientID(clientId)),
callback);
}

所以,这里指定的Client ID 其实是,AAD中所注册的一个应用(服务主体),而这个主体可以根据需求授予不同的权限,acquireToken就是根据用户验证成功后,生成这个主题所拥有的权限JWT令牌(Token),获取到Token后,就拥有了访问Azure中资源API的授权.

如何来获取这个Client ID呢?

  • 并在Onwed Applications 中选择,进入详细页面或就是当前页面,获取Application(Client) ID

特别注意:这个App必须开启 “Allow public client flows“ 才能成功获取到 Token。 默认情况下,这里选择的是No。 如果不开启这一步,将会收到错误消息:"error_description":"AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.

开启方式为:点击这个App的名称,进入详细页面,选择Authentication,滑动到最底部,选择“Allow public client flows”。

完成参考实例代码

1:在POM.XML文件中添加adal4j依赖

    <dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<version>1.2.0</version>
</dependency>

2:示例代码

package com.example;

import java.net.MalformedURLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult; /**
* Hello world!
*
*/
public class App {
public static void main(String[] args) throws InterruptedException, ExecutionException, MalformedURLException {
System.out.println("Hello World!"); ExecutorService service = Executors.newFixedThreadPool(1);
String AUTHORITY = "https://login.chinacloudapi.cn/<tenant id >"; // AzureAuthority String YOUR_Client_ID="7b61c392-xxxx-xxxx-xxxx-xxxxxxxxxxx";
String username = "xxxx@xxxx.xxx.onmschina.cn";
String password = "xxxxxxxxxxx";
AuthenticationContext context = new AuthenticationContext(AUTHORITY, false, service);
Future<AuthenticationResult> future = context.acquireToken("https://microsoftgraph.chinacloudapi.cn/", YOUR_Client_ID,
username, password, null);
AuthenticationResult result = future.get(); System.out.println("Access Token - " + result.getAccessToken());
System.out.println("Refresh Token - " + result.getRefreshToken());
System.out.println("ID Token - " + result.getIdToken()); }
}

(PS: 使用的 username, password就是登录Azure的用户名和密码

测试结果:

获取Token成功。

可以通过一个公用网站 jwt.io 来解析Token: https://jwt.io/, 它可以解析出Token内容,让我们可读。

参考资料

Azure China developer guide:https://docs.microsoft.com/en-us/azure/china/resources-developer-guide#check-endpoints-in-azure

 

Azure Active Directory libraries for Java: https://docs.microsoft.com/en-us/java/api/overview/azure/activedirectory?view=azure-java-stable#client-library

【Azure Developer】使用 adal4j(Azure Active Directory authentication library for Java)如何来获取Token呢的更多相关文章

  1. Enabling Active Directory Authentication for VMWare Server running on Linux《转载》

    Enabling Active Directory Authentication for VMWare Server running on Linux Version 0.2 - Adam Breid ...

  2. Weblogic中配置Active Directory Authentication Provider

    其要点或者容易出错的关键点是:(<>及其中说明代表需要替换的内容)         Host: ads.yourdomain.com         Host填AD服务器的域名或IP    ...

  3. 【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率

    问题描述 在Azure上创建虚拟机(VM)后,在门户上可以查看监控指标(Metrics),如CPU Usage,Memory,Disk I/O等.那如何通过Java 代码获取到这些指标呢? 关于VM ...

  4. 【Azure Developer】解决Azure Key Vault管理Storage的示例代码在中国区Azure遇见的各种认证/授权问题 - C# Example Code

    问题描述 使用Azure密钥保管库(Key Vault)来托管存储账号(Storage Account)密钥的示例中,从Github中下载的示例代码在中国区Azure运行时候会遇见各种认证和授权问题, ...

  5. Active Directory Authentication in ASP.NET MVC 5 with Forms Authentication and Group-Based Authorization

    I know that blog post title is sure a mouth-full, but it describes the whole problem I was trying to ...

  6. SQL Server ->> 使用Azure Active Directory Authentication连接到Azure SQL Database

    SQL Server 2016以后支持Azure AD集成验证,这当中有些数据驱动必须在高版本才可以使用,支持的包括sqlcmd,SSDT,JDBC,ODBC,SSMS等. 对于SSIS来讲,我们需要 ...

  7. 【Azure Developer】使用 Azure Python SDK时,遇见 The resource principal named https://management.azure.com was not found in the tenant China Azure问题的解决办法

    问题描述 在使用Python SDK时候,登录到China Azure (Mooncake)并访问AlertsManagement资源时候,时常遇见  EnvironmentCredential: A ...

  8. 【Azure Developer】在Azure Resource Graph Explorer中查看当前订阅下的所有资源信息列表并导出(如VM的名称,IP地址内网/公网,OS,区域等)

    问题描述 通过Azure的Resource Graph Explorer(https://portal.azure.cn/#blade/HubsExtension/ArgQueryBlade),可以查 ...

  9. 【Azure Developer】使用Azure PubSub服务示例代码时候遇见了.NET 6.0的代码转换问题

    问题描述 当本地环境中安装.NET 6.0后,用指令 dotnet new web 或  dotnet new console 生成的项目,使用的都是新模板生成的Program.cs文件.里面去掉了n ...

随机推荐

  1. java动态代理--代理接口无实现类

    转载:https://blog.csdn.net/weixin_45674354/article/details/103246715 1.接口定义: package cn.proxy; public ...

  2. jQuery--表单的过滤

    1.表单过滤器的介绍 :input 所有表单元素(<input>/<select>/<textarea>/<button>) :text 文本框< ...

  3. Mybatis框架基础入门(七)--关联查询

    1.一对一查询 1.1 使用resultType接收查询结果 修改pojo类 public class OrderUser extends order { private String usernam ...

  4. Oracle入门基础(九)一一创建表和管理表

    练习:查询每一年入职人数及总人数 SQL> select count(*) Total, 2 sum(decode(to_char(hiredate,'yyyy'),'1980',1,0)) & ...

  5. Java中8种基本数据类型是哪些

    1 public class Ceshi { 2 int a; 3 double b; 4 boolean c; 5 char d; 6 float f; 7 byte e; 8 long h; 9 ...

  6. RocketMQ实现分布式事务

    相关文章:http://www.uml.org.cn/zjjs/201810091.asp(深入理解分布式事务,高并发下分布式事务的解决方案) 三种分布式事务: 1.基于XA协议的两阶段提交 2.消息 ...

  7. linux环境下搭建solr服务器--单机版

    前提需要在安装好jdk和tomcat,本人用的是jdk1.8+tomcat8.5+solr4.10. 第一步:安装linux.jdk.tomcat.(这步都是比较简单的,就不多说了) 第二步:把sol ...

  8. 自制jq分页插件

    由于第一次写jq插件,中间有借鉴别人的代码. (function(){ var ms = { fillHtml: function(obj, option) { obj.empty(); var to ...

  9. js 简易模块加载器 示例分析

    前端模块化 关注前端技术发展的各位亲们,肯定对模块化开发这个名词不陌生.随着前端工程越来越复杂,代码越来越多,模块化成了必不可免的趋势. 各种标准 由于javascript本身并没有制定相关标准(当然 ...

  10. 用css动态实现圆环百分比分配——初探css3动画

    最近的小程序项目有个设计图要求做一个圆环,两种颜色分配,分别代表可用金额和冻结金额.要是就直接这么显示,感觉好像挺没水平??于是我决定做个动态! 在mdn把新特性gradients(渐变).trans ...