Ustawienie Azure AD i uwierzytelnianie Microsoft Graph

Aspose.Email for Java zapewnia pełną integrację z Microsoft Graph, umożliwiając deweloperom zarządzanie wiadomościami, kontaktami, kalendarzami i zadaniami z kont Microsoft 365. Ten przewodnik prowadzi Cię przez tworzenie aplikacji Azure AD i konfigurowanie uwierzytelniania, aby rozpocząć programowanie z Aspose.Email GraphClient.

Przed użyciem API Microsoft Graph z Aspose.Email musisz zarejestrować aplikację w Azure Active Directory (Azure AD) i skonfigurować uwierzytelnianie. Ta strona omawia:

  • Tworzenie aplikacji Azure AD (projekt).

  • Przydzielanie niezbędnych uprawnień Microsoft Graph.

  • Generowanie poświadczeń (client ID, client secret, tenant ID).

  • Uwierzytelnianie w Javie przy użyciu dostawców tokenów Aspose.Email.

Po zakończeniu będziesz gotowy do współpracy z Microsoft Graph z poziomu aplikacji Java.

1. Utwórz aplikację Azure AD

Postępuj zgodnie z poniższymi krokami, aby zarejestrować swoją aplikację w portalu Azure:

  1. Zaloguj się do Portal Azure.
  2. Przejdź do Azure Active DirectoryApp RegistrationsNew Registration.

todo:image_alt_text

  1. Wprowadź Name dla swojej aplikacji (np. AsposeEmailGraphApp).
  2. Wybierz obsługiwane typy kont:
    • Jednodzierżawca (jeśli tylko Twoja organizacja będzie go używać)
    • Wielodzierżawcowy (jeśli wiele organizacji potrzebuje dostępu)
  3. Opcjonalnie ustaw Redirect URI (wymagane dla interaktywnego lub webowego uwierzytelniania).
  4. Kliknij Register.

todo:image_alt_text

2. Utwórz client secret

  1. Po rejestracji przejdź do Certificates & SecretsNew Client Secret.
  2. Dodaj opis oraz okres ważności.

todo:image_alt_text

  1. Skopiuj wygenerowaną wartość secret – nie zobaczysz jej ponownie.

Trzymaj client secret w bezpiecznym miejscu; jest wymagany do uwierzytelniania poufnego klienta.

Powinieneś zobaczyć panel nowo zarejestrowanych aplikacji.

todo:image_alt_text

3. Skonfiguruj uprawnienia Microsoft Graph

  1. Przejdź do API PermissionsAdd a PermissionMicrosoft Graph.
  2. Wybierz typ uprawnień: Delegated lub Application, w zależności od scenariusza.
  3. Dodaj uprawnienia wymagane dla operacji Aspose.Email:
    • Contacts.ReadWrite – aby zarządzać kontaktami
    • Calendars.ReadWrite – aby zarządzać kalendarzami
    • Mail.ReadWrite – aby odczytywać i wysyłać wiadomości
    • Tasks.ReadWrite – aby zarządzać zadaniami
  4. Kliknij Grant Admin Consent, jeśli to konieczne.

todo:image_alt_text

4. Zezwalaj na przepływy klientów publicznych

Określ, czy aplikacja jest klientem publicznym. Odpowiednie dla aplikacji korzystających z przepływów tokenów, które nie używają URI przekierowania.

todo:image_alt_text

5. Uwierzytelnianie Microsoft Graph

Obsługiwane metody uwierzytelniania w Aspose.Email

| Dostawca tokenów | Przypadek użycia | | ——————————– | ————————————————————————————— | | AzureConfidentialTokenProvider | Klient poufny (client ID + secret) dla aplikacji po stronie serwera | | AzureROPCConfiguration | Poświadczenia właściciela zasobu (nazwa użytkownika + hasło) dla scenariuszy nieinteraktywnych | | AzurePublicTokenProvider | Klient publiczny (logowanie interaktywne) | | AzureTokenProviderBase | Klasa bazowa dla własnych implementacji uwierzytelniania |

Uwierzytelnianie przy użyciu poufnego klienta

Użyj AzureConfidentialTokenProvider do uwierzytelnienia, gdy posiadasz client ID, client secret i tenant ID:

AzureConfidentialTokenProvider provider = new AzureConfidentialTokenProvider(
    tenantId,
    clientId,
    clientSecret
);

IGraphClient client = GraphClient.getClient(provider, tenantId);
client.setResource(ResourceType.Users);
client.setResourceId(username);
client.setEndpoint("https://graph.microsoft.com");

To konfiguruje w pełni uwierzytelnionego IGraphClient gotowego do interakcji z Microsoft Graph.

Uwierzytelnianie przy użyciu ROPC (nazwa użytkownika i hasło)

W scenariuszach, w których posiadasz nazwę użytkownika i hasło, użyj AzureROPCConfiguration:

AzureROPCConfiguration ropcConfig = new AzureROPCConfiguration(
    tenantId,
    clientId,
    clientSecret,
    username,
    password
);

IGraphClient client = GraphClient.getClient(ropcConfig, tenantId);
client.setResource(ResourceType.Users);
client.setResourceId(username);
client.setEndpoint("https://graph.microsoft.com");

Własne dostawcy tokenów dla Microsoft Graph

Aspose.Email for Java integruje się z Microsoft Graph poprzez IGraphClient interfejs. Aby uwierzytelnić żądania, potrzebna jest implementacja ITokenProvider jest wymagane. Chociaż większość deweloperów korzysta z wbudowanych dostawców uwierzytelniania, istnieją sytuacje, w których możesz chcieć stworzyć własnego dostawcę, np. przy pracy z przepływem Resource Owner Password Credentials (ROPC).

1. Implementuj ITokenProvider przy użyciu AzureROPCTokenProvider

Ta klasa zapewnia implementację ITokenProvider przy użyciu przepływu Azure Resource Owner Password Credentials (ROPC). Poniższy przykład służy wyłącznie celom demonstracyjnym. W środowisku produkcyjnym zalecamy stosowanie bardziej bezpiecznych przepływów, takich jak poświadczenia klienta lub kod autoryzacji z PKCE.

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 = getToken();

        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> getToken() {
        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();
    }
}

2. Utwórz obiekt ITokenProvider

Ten IGraphClient interfejs jest odpowiedzialny za budowanie żądań, ich wysyłanie do Microsoft Graph oraz obsługę odpowiedzi. Aby utworzyć instancję IGraphClient, musisz dostarczyć implementację ITokenProvider. Dostawca tokenów uwierzytelnia żądania, dostarczając ważny token dostępu OAuth.

Poniższy przykład kodu demonstruje, jak utworzyć podstawową implementację w miejscu ITokenProvider interfejs, który jest wymagany do uwierzytelniania żądań Microsoft Graph:

ITokenProvider tokenProvider = new ITokenProvider() {
    Date expirationDate = null;

    @Override
    public void dispose() {
        // Clean up resources if necessary
    }

    @Override
    public OAuthToken getAccessToken(boolean ignoreExistingToken) {
        // Retrieve an OAuth access token.
        // If ignoreExistingToken is true, always request a new token.
        // Otherwise, return the existing token if it is valid, or request a new one.
        return null;
    }

    @Override
    public OAuthToken getAccessToken() {
        // Return a valid OAuth token.
        // If no valid token exists, request a new one.
        return new OAuthToken("token", expirationDate);
    }
};

3. Używanie własnego dostawcy tokenów

Po ITokenProvider jest skonfigurowany, możesz utworzyć GraphClient instancję. Ten klient będzie używał podanego dostawcy tokenów do uwierzytelniania przy wywoływaniu Microsoft Graph.

ITokenProvider provider = new AzureROPCTokenProvider(
        tenantId,
        clientId,
        clientSecret,
        userName,
        password,
        new String[] {"https://graph.microsoft.com/.default"}
);

IGraphClient client = GraphClient.getClient(provider, tenantId);
client.setResource(ResourceType.Users);
client.setResourceId(userName);
client.setEndpoint("https://graph.microsoft.com");

// Now you can call Microsoft Graph APIs
var folders = client.listFolders(null);
for (GraphFolderInfo folder : folders) {
    System.out.println(folder.getDisplayName());
}

Po utworzeniu i uwierzytelnieniu klienta możesz rozpocząć wysyłanie żądań do usług Microsoft Graph.