Microsoft Graph 实用功能
在 Azure Active Directory 管理中心创建项目
将在 Azure Active Directory 管理中心为拥有 MS Office 帐户的用户创建一个项目。
在 Azure Active Directory 管理中心创建项目的步骤
以下是创建 Azure Active Directory 管理中心项目的分步教程。
1. 前往 Azure Active Directory 并使用您的 MS Office 凭据登录。
Azure Active Directory 链接 - https://aad.portal.azure.com/
2. 在您的租户中创建 Azure AD 应用程序。
在左侧面板点击 Azure Active Directory 标签。这将打开 Azure Active Directory 的页面。在该页面会看到 应用注册 标签。这是注册 Azure AD 应用程序的起点。此页面允许您为 Azure AD 创建新应用程序。
点击 新建注册 按钮来创建新应用程序。

3. 现在您会看到新的应用注册页面。
- 名称 将作为您的应用程序名称。
- 受支持的帐户类型 此部分将限制访问。
点击 注册 按钮。

4. 您应该会看到新注册的应用程序页面。
- 应用程序(客户端)ID 您的应用程序 ID。
- 目录(租户)ID Azure AD 租户 ID。

5. 为 Microsoft Graph API 授予权限。
点击 API 权限 标签。
Azure 已为您的应用程序授予 User.Read 委托权限。此权限允许我们读取已登录用户的用户信息。这些是 Microsoft Graph API 的权限,亦可称为 作用域(Scopes)。
Microsoft Graph API 的完整作用域列表 - https://docs.microsoft.com/en-us/graph/permissions-reference。
点击 + 添加权限 按钮并选择 Microsoft Graph。
点击 委托权限。现在您可以看到 Microsoft Graph API 可用的权限列表。
选择所需权限,点击 添加权限 按钮。
点击 授予管理员同意 按钮。

6. 允许公共客户端流程。
指定应用程序是否为公共客户端。适用于使用不需要重定向 URI 的令牌授权流程的应用程序。

7. 为应用程序创建密钥

辅助类
以下辅助类是运行本节代码所必需的。这些类仅用于演示简化。
AzureROPCTokenProvider 类
该接口的实例 IGraphClient 类负责构建请求、发送至 Microsoft Graph API 并处理响应。要创建此类的新实例,您需要提供一个实例 ITokenProvider,可对 Microsoft Graph 的请求进行身份验证。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
* Azure resource owner password credential (ROPC) token provider
* https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
* https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
* https://portal.azure.com
* https://developer.microsoft.com/en-us/graph/graph-explorer/#
* token parser https://jwt.io
* </p>
*/
class AzureROPCTokenProvider implements ITokenProvider {
private static final String GRANT_TYPE = "password";
private final String clientId;
private final String clientSecret;
private final String userName;
private final String password;
private final String tenant;
private final String scope;
private OAuthToken token;
public AzureROPCTokenProvider(String tenant, String clientId, String clientSecret,
String userName, String password, String[] scopeAr) {
this.tenant = tenant;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.userName = userName;
this.password = password;
this.scope = joinToStr(scopeAr, " ");
}
public synchronized OAuthToken getAccessToken(boolean ignoreExistingToken) {
if (this.token != null && !this.token.getExpired() && !ignoreExistingToken)
return this.token;
token = null;
Map<String, String> tokenArgs = geToken();
java.util.Calendar c = java.util.Calendar.getInstance();
c.add(java.util.Calendar.SECOND, Integer.parseInt(tokenArgs.get("expires_in")));
token = new OAuthToken(tokenArgs.get("access_token"), TokenType.AccessToken, c.getTime());
return token;
}
public final OAuthToken getAccessToken() {
return getAccessToken(false);
}
public void dispose() {
}
private String getEncodedParameters() {
return "client_id=" + urlEncode(clientId) + "&scope=" + urlEncode(scope) + "&username=" + urlEncode(userName)
+ "&password=" + urlEncode(password) + "&grant_type="
+ urlEncode(GRANT_TYPE);
}
private String getUri() {
if (tenant == null || tenant.trim().isEmpty())
return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
else
return "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/token";
}
private Map<String, String> geToken() {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(getUri()).openConnection();
connection.setRequestMethod("POST");
byte[] requestData = getEncodedParameters().getBytes(StandardCharsets.UTF_8);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", "" + requestData.length);
final OutputStream st = connection.getOutputStream();
try {
st.write(requestData, 0, requestData.length);
} finally {
st.flush();
st.close();
}
connection.connect();
if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
throw new IllegalAccessError("Operation failed: " + connection.getResponseCode() + "/" +
connection.getResponseMessage() + "\r\nDetails:\r\n{2}"
+ readInputStream(connection.getErrorStream()));
}
String responseText = readInputStream(connection.getInputStream());
Map<String, String> result = new HashMap<>();
String[] fromJsonToKeyValue = responseText.replace("{", "").replace("}", "")
.replace("\"", "").replace("\r", "")
.replace("\n", "").split(",");
for (String keyValue : fromJsonToKeyValue) {
String[] pair = keyValue.split(":");
String name = pair[0].trim().toLowerCase();
String value = urlDecode(pair[1].trim());
result.put(name, value);
}
return result;
} catch (IOException e) {
throw new IllegalAccessError(e.getMessage());
}
}
static String urlEncode(String value) {
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
throw new IllegalAccessError(e.getMessage());
}
}
static String urlDecode(String value) {
try {
return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
throw new IllegalAccessError(e.getMessage());
}
}
static String readInputStream(InputStream is) {
if (is == null)
return "";
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder result = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
result.append(line);
}
} catch (IOException e) {
// ignore
}
return result.toString();
}
static String joinToStr(String[] arr, String sep) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
if (i > 0)
sb.append(sep);
sb.append(arr[i]);
}
return sb.toString();
}
}