Linux kodu örnekleri

Önemli

Mart 2020'den önce yayımlanan Microsoft Rights Management Service SDK sürümleri kullanım dışı bırakılmıştır; önceki sürümleri kullanan uygulamaların Mart 2020 sürümünü kullanacak şekilde güncelleştirilmiş olması gerekir. Tüm ayrıntılar için kullanımdan kaldırma bildirimine bakın.

Microsoft Rights Management Service SDK'sı için başka geliştirme planlanmıyor. Sınıflandırma, etiketleme ve koruma hizmetleri için Microsoft Bilgi Koruması SDK'sının benimsenmesini kesinlikle öneririz.

Bu konuda, RMS SDK’in Linux sürümü için önemli senaryolar ve kod öğeleri sunulacaktır.

Aşağıdaki kod parçacıkları rms_sample vermsauth_sample örnek uygulamalardan alınıyor. Daha fazla bilgi için, GitHub deposunda örneklere bakın.

Senaryo: Korumalı bir dosyada koruma ilkesi bilgilerine erişim

RMS korumalı dosyayı açar veokurKaynak: rms_sample/mainwindow.cpp

Açıklama: Kullanıcıdan dosya adını aldıktan sonra, sertifikaları okuma (bkz. MainWindow::addCertificates), İstemci kimliği ve Yönlendirme URL’siyle yetki geri çağırmayı ayarlama, ConvertFromPFile çağırma (aşağıdaki kod örneğine bakın), sonra koruma ilke adını, açıklamayı ve içerik geçerlilik tarihini okuma.

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

Korumalı dosya oluşturmastreamSource: rms_sample/pfileconverter.cpp

Açıklama: Bu yöntem, sdk yöntemi aracılığıyla geçirilen yedekleme akışından korumalı bir dosya akışı oluşturur, ProtectedFileStream::Acquire, daha sonra çağırana döndürülür.

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;
  }

Senaryo: Bir şablon kullanarak yeni bir korumalı dosya oluşturma

Kullanıcının seçtiği şablonla bir dosyayıkorurKaynak: rms_sample/mainwindow.cpp

Açıklama: Kullanıcıdan dosya adını aldıktan sonra, sertifikaları okuma (bkz. MainWindow::addCertificates), ve İstemci kimliği ve Yönlendirme URL’siyle yetki geri çağırmayı ayarlama, seçilen dosya ConvertToPFileTemplates çağrılarak korunur (aşağıdaki kod örneğine bakın).

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

Şablondan oluşturulan bir ilkeyi kullanarak dosyayıkorurKaynak: rms_sample/pfileconverter.cpp

Açıklama: Kullanıcıyla ilişkili şablonların listesi getirilir ve daha sonra seçilen şablon dosyayı korumak için kullanılan bir ilke oluşturmak için kullanılır.

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);
  }
  }

İlke verilen bir dosyayıkorurKaynak: rms_sample/pfileconverter.cpp

Açıklama: Verilen ilkeyi kullanan bir korunan dosya akışı oluşturun, sonra bu dosyayı koruyun.

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

Senaryo: Özel koruma kullanarak bir dosyayı koruma

Özel koruma kullanarak dosyayıkorurKaynak: rms_sample/mainwindow.cpp

Açıklama: Kullanıcıdan dosya adını aldıktan sonra, sertifikaları okuma (bkz. MainWindow::addCertificates), kullanıcıdan hak bilgilerini toplama ve İstemci kimliği ve Yönlendirme URL’siyle yetki geri çağırmayı ayarlama, seçilen dosya ConvertToPFilePredefinedRights çağrılarak yansıtılır(aşağıdaki kod örneğine bakın).

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

Kullanıcıya seçili hakları veren bir koruma ilkesioluştururKaynak: rms_sample/pfileconverter.cpp

Açıklama: İlke tanımlayıcısı oluşturun ve bunu kullanıcının hak bilgileriyle doldurun, sonra kullanıcı ilkesi oluşturmak için ilke tanımlayıcısı kullanın. Bu ilke seçilen dosyayı bir ConvertToPFileUsingPolicy çağrısıyla korumak için kullanılır (Bu, bu konunun önceki bölümünde açıklanmıştır).

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 - destekleyen bir yöntem

WorkerThread() yöntemi önceki iki örnek senaryo tarafından çağrılır; aşağıdaki şekilde Korumalı dosya akışı oluşturma ve İlke verilen bir dosyayı korur:

C++:

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

Destekleyen yöntem, WorkerThread()

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

Senaryo: RMS kimlik doğrulama

Aşağıdaki örnekler, iki farklı kimlik doğrulama yaklaşımını gösterir; Kullanıcı Arabirimi kullanarak ve Kullanıcı Arabirimi olmadan Azure kimlik doğrulama oAuth2 belirteci alma UISource ile oAuth2 Kimlik Doğrulama Belirteci Alma: rmsauth_sample/mainwindow.cpp

1. Adım: rmsauth::FileCache nesnesinin paylaşılan noktasını oluşturun. Açıklama: Önbellek yolunu ayarlayabilir veya varsayılanı kullanabilirsiniz.

C++:

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

2. adım: rmsauth::AuthenticationContext nesnesi oluşturun Açıklama: Azure yetki URI’si ve FileCache nesnesi belirtin.

C++:

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

3. Adım: authContext nesnesinin acquireToken yöntemini çağırın ve sonraki parametreleri belirtin: Açıklama:

  • İstenen kaynak -erişmek istediğiniz korumalı kaynak
  • Benzersiz istemci kimliği -genellikle bir GUID
  • Yeniden yönlendirme URI'si -kimlik doğrulama belirteci getirildikten sonra yeniden başvurulacak URI
  • Kimlik doğrulama istemi davranışı - PromptBehavior::Auto olarak ayarlarsanız, kitaplık önbelleği kullanmaya ve gerekirse belirteci yenilemeye çalışır
  • Kullanıcı Kimliği - komut istemi penceresinde görüntülenen kullanıcı adı

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"));

4. adım: Sonuçtan erişim belirteci alın Açıklama: result-> accessToken() yöntemini çağırın

Not Kimlik doğrulama kitaplığı yöntemlerinden herhangi biri rmsauth::Exception'a neden olabilir

UISource olmadan oAuth2 Kimlik Doğrulama Belirteci Alma: rmsauth_sample/mainwindow.cpp

1. adım: rmsauth::FileCache nesnesine ait bir paylaşılan nokta oluşturun Açıklama: Önbellek yolunu ayarlayabilir veya varsayılanı kullanabilirsiniz

C++:

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

2. adım: UserCredential nesnesi oluşturun Açıklama: kullanıcı oturum açma bilgileri ve parola belirtin

C++:

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

3. adım: rmsauth::AuthenticationContext nesnesi oluşturun Açıklama: Azure yetki URI’si ve FileCache nesnesi belirtin

C++:

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

4. Adım: authContext'inacquireToken yöntemini çağırın ve parametreleri belirtin:

  • İstenen kaynak -erişmek istediğiniz korumalı kaynak
  • Benzersiz istemci kimliği -genellikle bir GUID
  • Kullanıcı kimlik bilgileri -oluşturulan nesneyi geçirin

C++:

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

5. adım: Sonuçtan erişim belirteci alın Açıklama: result-> accessToken() yöntemini çağırın

Not Kimlik doğrulama kitaplığı yöntemlerinden herhangi biri rmsauth::Exception'a neden olabilir