Exemples de code LinuxLinux code examples

Important

Les versions du kit de développement logiciel (SDK) Microsoft Rights Management service antérieures au 2020 mars sont dépréciées. les applications qui utilisent des versions antérieures doivent être mises à jour pour utiliser la version de mars 2020.Versions of the Microsoft Rights Management Service SDK released prior to March 2020 are deprecated; applications using earlier versions must be updated to use the March 2020 release. Pour plus d’informations, consultez l' avis de désapprobation.For full details, see the deprecation notice.

Aucune autre amélioration n’est prévue pour le kit de développement logiciel (SDK) du service Microsoft Rights Management.No further enhancements are planned for the Microsoft Rights Management Service SDK. Nous vous recommandons vivement d’adopter le Kit de développement logiciel (SDK) Microsoft information protection pour les services de classification, d’étiquetage et de protection.We strongly recommend adoption of the Microsoft Information Protection SDK for classification, labeling, and protection services.

Cette rubrique présente les éléments de code et les scénarios importants pour la version Linux du Kit RMS SDK.This topic introduces you to important scenarios and code elements for the Linux version of the RMS SDK.

Les extraits de code ci-dessous sont tirés des exemples d’applications, de RMS _ Sample et *rmsauth _ *.The code snippets below are from the sample applications, rms_sample and rmsauth_sample. Pour plus d’informations, consultez samples dans le dépôt GitHub.For more information, see samples at the GitHub repository.

Scénario : Accéder aux informations de stratégie de protection à partir d’un fichier protégéScenario: Access protection policy information from a protected file

Ouvre et lit un fichier protégé par RMS Source: RMS _ Sample/MainWindow. cppOpens and reads an RMS protected file Source: rms_sample/mainwindow.cpp

Description : Après obtention d’un nom de fichier auprès de l’utilisateur, lecture des certificats (voir MainWindow::addCertificates), configuration du rappel d’autorisation avec l’ID client et l’URL de redirection, appel de ConvertFromPFile (voir l’exemple de code suivant), puis lecture de la description, de la date de validité du contenu et du nom de la stratégie de protection.Description: After getting a file name from the user, reading the certificates (see MainWindow::addCertificates), setting up the authorization callback with Client ID and Redirect URL, calling ConvertFromPFile (see following code example), then reading out the protection policy name, description and content validity date.

C++:C++:

  void MainWindow::ConvertFromPFILE(const string& fileIn,
      const string& clientId,
      const string& redirectUrl,
      const string& clientEmail) 
  {
  // add trusted certificates using HttpHelpers of RMS and Auth SDKs
  addCertificates();
  
  // create shared in/out streams
  auto inFile = make_shared<ifstream>(
  fileIn, ios_base::in | ios_base::binary);
  
  if (!inFile->is_open()) {
   AddLog("ERROR: Failed to open ", fileIn.c_str());
  return;
  }
  
  string fileOut;
  
  // generate output filename
  auto pos = fileIn.find_last_of('.');
  
  if (pos != string::npos) {
   fileOut = fileIn.substr(0, pos);
  }
  
   // create streams
  auto outFile = make_shared<fstream>(
  fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);
  
  if (!outFile->is_open()) {
   AddLog("ERROR: Failed to open ", fileOut.c_str());
   return;
    }
  
  try
  {
  // create authentication context
  AuthCallback auth(clientId, redirectUrl);
  
  // process conversion
  auto pfs = PFileConverter::ConvertFromPFile(
    clientEmail,
    inFile,
    outFile,
    auth,
    this->consent);
  
  AddLog("Successfully converted to ", fileOut.c_str());
  }
  catch (const rmsauth::Exception& e)
  {
  AddLog("ERROR: ", e.error().c_str());
  }
  catch (const rmscore::exceptions::RMSException& e) {
  AddLog("ERROR: ", e.what());
  }
  inFile->close();
  outFile->close();
  }

Créer un flux de fichier protégé Source: RMS _ Sample/pfileconverter. cppCreate a protected file stream Source: rms_sample/pfileconverter.cpp

Description: cette méthode crée un flux de fichier protégé à partir du flux de sauvegarde passé via la méthode SDK, ProtectedFileStream :: Acquire, qui est ensuite retournée à l’appelant.Description: This method creates a protected file stream from the passed in backing stream through the SDK method, ProtectedFileStream::Acquire, which is then returned to the caller.

C++:C++:

  shared_ptr<GetProtectedFileStreamResult>PFileConverter::ConvertFromPFile(
  const string           & userId,
  shared_ptr<istream>      inStream,
  shared_ptr<iostream>     outStream,
  IAuthenticationCallback& auth,
  IConsentCallback       & consent)
  {
  auto inIStream = rmscrypto::api::CreateStreamFromStdStream(inStream);
  
  auto fsResult = ProtectedFileStream::Acquire(
  inIStream,
  userId,
  auth,
  consent,
  POL_None,
  static_cast<ResponseCacheFlags>(RESPONSE_CACHE_INMEMORY
                                  | RESPONSE_CACHE_ONDISK));
  
  if ((fsResult.get() != nullptr) && (fsResult->m_status == Success) &&
    (fsResult->m_stream != nullptr)) {
  auto pfs = fsResult->m_stream;
  
  // preparing
  readPosition  = 0;
  writePosition = 0;
  totalSize     = pfs->Size();
  
  // start threads
  for (size_t i = 0; i < THREADS_NUM; ++i) {
    threadPool.push_back(thread(WorkerThread,
                                static_pointer_cast<iostream>(outStream), pfs,
                                false));
  }
  
  for (thread& t: threadPool) {
    if (t.joinable()) {
      t.join();
    }
  }
  }
    return fsResult;
  }

Scénario : Créer un fichier protégé à l’aide d’un modèleScenario: Create a new protected file using a template

Protège un fichier avec un modèle sélectionné par l’utilisateur Source: RMS _ Sample/MainWindow. cppProtects a file with a user selected template Source: rms_sample/mainwindow.cpp

Description : Après obtention d’un nom de fichier auprès de l’utilisateur, lecture des certificats (voir MainWindow::addCertificates) et configuration du rappel d’autorisation avec l’ID client et l’URL de redirection, le fichier sélectionné est protégé en appelant ConvertToPFileTemplates (voir l’exemple de code suivant).Description: After getting a file name from the user, reading the certificates (see MainWindow::addCertificates) and setting up the authorization callback with Client ID and Redirect URL, the selected file is protected by calling ConvertToPFileTemplates (see following code example).

C++:C++:

  void MainWindow::ConvertToPFILEUsingTemplates(const string& fileIn,
                                            const string& clientId,
                                            const string& redirectUrl,
                                            const string& clientEmail) 
  {
  // generate output filename
  string fileOut = fileIn + ".pfile";
  
  // add trusted certificates using HttpHelpers of RMS and Auth SDKs
  addCertificates();
  
  // create shared in/out streams
  auto inFile = make_shared<ifstream>(
  fileIn, ios_base::in | ios_base::binary);
  auto outFile = make_shared<fstream>(
  fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);
  
  if (!inFile->is_open()) {
  AddLog("ERROR: Failed to open ", fileIn.c_str());
  return;
  }
  
  if (!outFile->is_open()) {
  AddLog("ERROR: Failed to open ", fileOut.c_str());
  return;
  }
  
  // find file extension
  string fileExt;
  auto   pos = fileIn.find_last_of('.');
  
  if (pos != string::npos) {
  fileExt = fileIn.substr(pos);
  }
  
  try {
  // create authentication callback
  AuthCallback auth(clientId, redirectUrl);
  
  // process conversion
  PFileConverter::ConvertToPFileTemplates(
    clientEmail, inFile, fileExt, outFile, auth,
    this->consent, this->templates);
  
  AddLog("Successfully converted to ", fileOut.c_str());
  }
 catch (const rmsauth::Exception& e) {
  AddLog("ERROR: ", e.error().c_str());
  outFile->close();
  remove(fileOut.c_str());
  }
  catch (const rmscore::exceptions::RMSException& e) {
  AddLog("ERROR: ", e.what());
  
  outFile->close();
  remove(fileOut.c_str());
  }
  inFile->close();
  outFile->close();
  }

Protège un fichier à l’aide d’une stratégie créée à partir d’un modèle Source: RMS _ Sample/pfileconverter. cppProtects a file using a policy created from a template Source: rms_sample/pfileconverter.cpp

Description: Une liste de modèles associés à l’utilisateur est récupérée et le modèle sélectionné est ensuite utilisé pour créer une stratégie qui, à son tour, est utilisée pour protéger le fichier.Description: A list of templates associated with the user is fetched and selected template is then used to create a policy which in turn is used to protect the file.

C++:C++:

  void PFileConverter::ConvertToPFileTemplates(const string           & userId,
                                           shared_ptr<istream>      inStream,
                                           const string           & fileExt,
                                           std::shared_ptr<iostream>outStream,
                                           IAuthenticationCallback& auth,
                                           IConsentCallback& /*consent*/,
                                           ITemplatesCallback     & templ)
  {
  auto templates = TemplateDescriptor::GetTemplateList(userId, auth);
  
  rmscore::modernapi::AppDataHashMap signedData;
  
  size_t pos = templ.SelectTemplate(templates);
  
  if (pos < templates.size()) {
  auto policy = UserPolicy::CreateFromTemplateDescriptor(
    templates[pos],
    userId,
    auth,
    USER_AllowAuditedExtraction,
    signedData);
 
  ConvertToPFileUsingPolicy(policy, inStream, fileExt, outStream);
  }
  }

Protège un fichier à partir d’une stratégie Source: RMS _ Sample/pfileconverter. cppProtects a file given a policy Source: rms_sample/pfileconverter.cpp

Description: Créer un flux de fichier protégé à l’aide de la stratégie donnée, puis protéger ce fichier.Description: Create a protected file stream using the given policy then protect that file.

C++:C++:

  void PFileConverter::ConvertToPFileUsingPolicy(shared_ptr<UserPolicy>   policy,
                                             shared_ptr<istream>      inStream,
                                             const string           & fileExt,
                                             std::shared_ptr<iostream>outStream)
  {
  if (policy.get() != nullptr) {
  auto outIStream = rmscrypto::api::CreateStreamFromStdStream(outStream);
  auto pStream    = ProtectedFileStream::Create(policy, outIStream, fileExt);
  
  // preparing
  readPosition  = 0;
  writePosition = pStream->Size();
  
  inStream->seekg(0, ios::end);
  totalSize = inStream->tellg();
  
  // start threads
  for (size_t i = 0; i < THREADS_NUM; ++i) {
    threadPool.push_back(thread(WorkerThread,
                                static_pointer_cast<iostream>(inStream),
                                pStream,
                                true));
  }
  
  for (thread& t: threadPool) {
    if (t.joinable()) {
      t.join();
    }
  }
  
  pStream->Flush();
  }

Scénario : Protéger un fichier à l’aide de la protection personnaliséeScenario: Protect a file using custom protection

Protège un fichier à l’aide de la protection personnalisée Source: RMS _ Sample/MainWindow. cppProtects a file using custom protection Source: rms_sample/mainwindow.cpp

Description : Après obtention d’un nom de fichier auprès de l’utilisateur, lecture des certificats (voir MainWindow::addCertificates), collecte des informations sur les droits auprès de l’utilisateur et configuration du rappel d’autorisation avec l’ID client et l’URL de redirection, le fichier sélectionné est protégé en appelant ConvertToPFileTemplates (voir l’exemple de code suivant).Description: After getting a file name from the user, reading the certificates (see MainWindow::addCertificates), collecting rights information from the user, and setting up the authorization callback with Client ID and Redirect URL, the selected file is projected by calling ConvertToPFilePredefinedRights (see following code example).

C++:C++:

  void MainWindow::ConvertToPFILEUsingRights(const string            & fileIn,
                                         const vector<UserRights>& userRights,
                                         const string            & clientId,
                                         const string            & redirectUrl,
                                         const string            & clientEmail)
  {
  // generate output filename
  string fileOut = fileIn + ".pfile";
  
  // add trusted certificates using HttpHelpers of RMS and Auth SDKs
  addCertificates();
  
  // create shared in/out streams
  auto inFile = make_shared<ifstream>(
  fileIn, ios_base::in | ios_base::binary);
  auto outFile = make_shared<fstream>(
  fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);
  
  if (!inFile->is_open()) {
  AddLog("ERROR: Failed to open ", fileIn.c_str());
  return;
  }
  
  if (!outFile->is_open()) {
  AddLog("ERROR: Failed to open ", fileOut.c_str());
  return;
  }
  
  // find file extension
  string fileExt;
  auto   pos = fileIn.find_last_of('.');
  
  if (pos != string::npos) {
  fileExt = fileIn.substr(pos);
  }
  
  // is anything to add
  if (userRights.size() == 0) {
  AddLog("ERROR: ", "Please fill email and check rights");
  return;
  }
  
  
  try {
  // create authentication callback
  AuthCallback auth(clientId, redirectUrl);
  
  // process conversion
  PFileConverter::ConvertToPFilePredefinedRights(
    clientEmail,
    inFile,
    fileExt,
    outFile,
    auth,
    this->consent,
    userRights);
  
  AddLog("Successfully converted to ", fileOut.c_str());
  }
  catch (const rmsauth::Exception& e) {
  AddLog("ERROR: ", e.error().c_str());
  
  outFile->close();
  remove(fileOut.c_str());
  }
  catch (const rmscore::exceptions::RMSException& e) {
  AddLog("ERROR: ", e.what());
  
  outFile->close();
  remove(fileOut.c_str());
  }
  inFile->close();
  outFile->close();
  }

Crée une stratégie de protection donnant aux utilisateurs les droits sélectionnés Source: RMS _ Sample/pfileconverter. cppCreates a protection policy give user selected rights Source: rms_sample/pfileconverter.cpp

Description : Créer un descripteur de stratégie et le remplir avec les informations sur les droits de l’utilisateur, puis utiliser le descripteur de stratégie pour créer une stratégie utilisateur.Description: Create a policy descriptor and fill it with the user's rights information then, use the policy descriptor to create a user policy. Cette stratégie est utilisée pour protéger le fichier sélectionné par le biais d’un appel à ConvertToPFileUsingPolicy (voir la description fournie dans une section précédente de cette rubrique).This policy is used to protect the selected file via a call to ConvertToPFileUsingPolicy (see this described in a previous section of this topic).

C++:C++:

  void PFileConverter::ConvertToPFilePredefinedRights(
  const string            & userId,
  shared_ptr<istream>       inStream,
  const string            & fileExt,
  shared_ptr<iostream>      outStream,
  IAuthenticationCallback & auth,
  IConsentCallback& /*consent*/,
  const vector<UserRights>& userRights)
  {
  auto endValidation = chrono::system_clock::now() + chrono::hours(48);
  
  
  PolicyDescriptor desc(userRights);
  
  desc.Referrer(make_shared<string>("https://client.test.app"));
  desc.ContentValidUntil(endValidation);
  desc.AllowOfflineAccess(false);
  desc.Name("Test Name");
  desc.Description("Test Description");
  
  auto policy = UserPolicy::Create(desc, userId, auth,
                                 USER_AllowAuditedExtraction);
  ConvertToPFileUsingPolicy(policy, inStream, fileExt, outStream);

WorkerThread - méthode prise en chargeWorkerThread - a supporting method

La méthode WorkerThread() est appelée par deux des exemples de scénarios précédents (Créer un flux de fichier protégé et Protège un fichier conformément à une stratégie) de la manière suivante :The WorkerThread() method is called by two of the previous example scenarios; Create a protected file stream and Protects a file given a policy in the following manner:

C++:C++:

  threadPool.push_back(thread(WorkerThread,
                                static_pointer_cast<iostream>(outStream), pfs,
                                false));

Méthode de prise en charge, WorkerThread()Supporting method, WorkerThread()

C++:C++:

  static mutex   threadLocker;
  static int64_t totalSize     = 0;
  static int64_t readPosition  = 0;
  static int64_t writePosition = 0;
  static vector<thread> threadPool;
  
  static void WorkerThread(shared_ptr<iostream>           stdStream,
                       shared_ptr<ProtectedFileStream>pStream,
                       bool                           modeWrite) {
  vector<uint8_t> buffer(4096);
  int64_t bufferSize = static_cast<int64_t>(buffer.size());
  
  while (totalSize - readPosition > 0) {
  // lock
  threadLocker.lock();
  
  // check remain
  if (totalSize - readPosition <= 0) {
    threadLocker.unlock();
    return;
  }
  
  // get read/write offset
  int64_t offsetRead  = readPosition;
  int64_t offsetWrite = writePosition;
  int64_t toProcess   = min(bufferSize, totalSize - readPosition);
  readPosition  += toProcess;
  writePosition += toProcess;
  
  // no need to lock more
  threadLocker.unlock();
  
  if (modeWrite) {
    // stdStream is not thread safe!!!
    try {
      threadLocker.lock();
  
      stdStream->seekg(offsetRead);
      stdStream->read(reinterpret_cast<char *>(&buffer[0]), toProcess);
      threadLocker.unlock();
      auto written =
        pStream->WriteAsync(
          buffer.data(), toProcess, offsetWrite, std::launch::deferred).get();
  
      if (written != toProcess) {
        throw rmscore::exceptions::RMSStreamException("Error while writing data");
      }
    }
    catch (exception& e) {
      qDebug() << "Exception: " << e.what();
    }
  } else {
    auto read =
      pStream->ReadAsync(&buffer[0],
                         toProcess,
                         offsetRead,
                         std::launch::deferred).get();
  
    if (read == 0) {
      break;
    }
  
    try {
      // stdStream is not thread safe!!!
      threadLocker.lock();
  
      // seek to write
      stdStream->seekp(offsetWrite);
      stdStream->write(reinterpret_cast<const char *>(buffer.data()), read);
      threadLocker.unlock();
    }
    catch (exception& e) {
      qDebug() << "Exception: " << e.what();
    }
  }
  }
  }

Scénario : Authentification RMSScenario: RMS authentication

Les exemples suivants montrent deux approches d’authentification : obtention d’un jeton oAuth2 d’authentification Azure avec interface utilisateur et sans interface utilisateur.The following examples show two different authentication approaches; obtaining Azure Authentication oAuth2 token using UI and without UI. Acquisition du jeton d’authentification oAuth2 avec l’interface utilisateur Source: rmsauth _ Sample/MainWindow. cppAcquiring oAuth2 Authentication Token with UI Source: rmsauth_sample/mainwindow.cpp

Étape 1: créer un point partagé de l’objet Rmsauth :: FileCache .Step 1: Create a shared point of rmsauth::FileCache object. Description : Vous pouvez définir le chemin du cache ou utiliser la valeur par défaut.Description: You can set cache path or use default.

C++:C++:

  auto FileCachePtr = std::make_shared< rmsauth::FileCache>();

Étape 2 : Créer l’objet rmsauth::AuthenticationContext Description : Spécifier l’URI d’autorité Azure et l’objet FileCache.Step 2: Create rmsauth::AuthenticationContext object Description: Specify Azure authority URI and FileCache object.

C++:C++:

  AuthenticationContext authContext(
                            std::string("https://sts.aadrm.com/_sts/oauth/authorize"),
                            AuthorityValidationType::False,
                            FileCachePtr);

Étape 3: appelez la méthode acquireToken de l’objet authContext et spécifiez les paramètres suivants : Description :Step 3: Call acquireToken method of authContext object and specify next parameters: Description:

  • Ressource demandée : Ressource protégée à laquelle vous souhaitez accéderRequested resource - protected resource you want to access
  • ID du client unique : Généralement un GUIDClient unique ID - usually a GUID
  • URI de redirection : URI qui sera réadressé après récupération du jeton d’authentificationRedirection URI - the URI which will be readdressed after authentication token fetched
  • Comportement de l’invite d’authentification : Si vous définissez PromptBehavior::Auto, la bibliothèque essaie d’utiliser le cache et d’actualiser le jeton si nécessaireAuthentication prompt behavior - if you set PromptBehavior::Auto the library tries to use cache and refresh token if necessary
  • ID d’utilisateur : Nom d’utilisateur affiché dans la fenêtre d’inviteUser ID - User name displayed in the prompt window

C++:C++:

  auto result = authContext.acquireToken(
              std::string("api.aadrm.com"),
              std::string("4a63455a-cfa1-4ac6-bd2e-0d046cf1c3f7"),
              std::string("https://client.test.app"),
              PromptBehavior::Auto,
              std::string("john.smith@msopentechtest01.onmicrosoft.com"));

Étape 4 : Obtenir le jeton d’accès à partir du résultat Description : Appeler la méthode result-> accessToken()Step 4: Get access token from result Description: Call result-> accessToken() method

Remarque Toutes les méthodes de bibliothèque d’authentification peuvent lever rmsauth::ExceptionNote Any of the authentication library methods may raise rmsauth::Exception

Acquisition du jeton d’authentification oAuth2 sans interface utilisateur Source: rmsauth _ Sample/MainWindow. cppAcquiring oAuth2 Authentication Token without UI Source: rmsauth_sample/mainwindow.cpp

Étape 1 : Créer un point partagé de l’objet rmsauth::FileCache Description : Vous pouvez définir le chemin du cache ou utiliser la valeur par défautStep 1: Create a shared point of rmsauth::FileCache object Description: You can set cache path or use default

C++:C++:

  auto FileCachePtr = std::make_shared< rmsauth::FileCache>();

Étape 2 : Créer l’objet UserCredential Description : Spécifier la connexion utilisateur et le mot de passeStep 2:Create UserCredential object Description: Specify user login and password

C++:C++:

  auto userCred = std::make_shared<UserCredential>("john.smith@msopentechtest01.onmicrosoft.com",
                                               "SomePass");

Étape 3 : Créer l’objet rmsauth::AuthenticationContext Description : Spécifier l’URI d’autorité Azure et l’objet FileCacheStep 3:Create rmsauth::AuthenticationContext object Description: Specify Azure authority URI and FileCache object

C++:C++:

  AuthenticationContext authContext(
                      std::string("https://sts.aadrm.com/_sts/oauth/authorize"),
                      AuthorityValidationType::False,
                      FileCachePtr);

Étape 4: appelez la méthode acquireToken de authContext et spécifiez les paramètres :Step 4: Call the acquireToken method of authContext and specify parameters:

  • Ressource demandée : Ressource protégée à laquelle vous souhaitez accéderRequested resource - protected resource you want to access
  • ID du client unique : Généralement un GUIDClient unique ID - usually a GUID
  • Informations d’identification de l’utilisateur : passer l’objet crééUser credentials - pass the created object

C++:C++:

  auto result = authContext.acquireToken(
              std::string("api.aadrm.com"),
              std::string("4a63455a-cfa1-4ac6-bd2e-0d046cf1c3f7"),
              userCred);

Étape 5 : Obtenir le jeton d’accès à partir du résultat Description : Appeler la méthode result-> accessToken()Step 5: Get access token from result Description: Call result-> accessToken() method

Remarque Toutes les méthodes de bibliothèque d’authentification peuvent lever rmsauth::ExceptionNote Any of the authentication library methods may raise rmsauth::Exception