Příklady kódu pro LinuxLinux code examples

Toto téma vás seznámí s důležitými scénáři a elementy kódu verze RMS SDK pro Linux.This topic introduces you to important scenarios and code elements for the Linux version of the RMS SDK.

Uvedené fragmenty kódu jsou z ukázkových aplikací rms_sample a rmsauth_sample.The code snippets below are from the sample applications, rms_sample and rmsauth_sample. Další informace najdete v části ukázky v úložišti GitHub.For more information, see samples at the GitHub repository.

Scénář: Přístup k informacím o zásadě ochrany z chráněného souboruScenario: Access protection policy information from a protected file

Otevře a přečte soubor chráněný RMS. Zdroj: rms_sample/mainwindow.cppOpens and reads an RMS protected file Source: rms_sample/mainwindow.cpp

Popis: Po získání názvu souboru od uživatele se čtou certifikáty (viz MainWindow::addCertificates), nastavuje se zpětné volání autorizace pomocí ID klienta a adresy URL pro přesměrování, volá se ConvertFromPFile (viz následující ukázka kódu) a pak se čte název zásady, popis a datum platnosti obsahu.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 convertion
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();
}

Vytvoří datový proud chráněného souboru. Zdroj: rms_sample/pfileconverter.cppCreate a protected file stream Source: rms_sample/pfileconverter.cpp

Popis: Tato metoda vytvoří datový proud chráněného souboru z předaného pomocného datového proudu prostřednictvím metody SDK ProtectedFileStream::Aquire, který je poté vrácen volajícímu.Description: This method creates a protected file stream from the passed in backing stream through the SDK method, ProtectedFileStream::Aquire, 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énář: Vytvoření nového chráněného souboru pomocí šablonyScenario: Create a new protected file using a template

Chrání soubor pomocí šablony vybrané uživatelem. Zdroj: rms_sample/mainwindow.cppProtects a file with a user selected template Source: rms_sample/mainwindow.cpp

Popis: Po získání názvu souboru od uživatele, čtení certifikátů (viz MainWindow::addCertificates) a nastavení zpětného volání autorizace pomocí ID klienta a adresy URL pro přesměrování se vybraný soubor chrání voláním ConvertToPFileTemplates (viz následující ukázka kódu).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 convertion
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());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();
}

Chrání soubor pomocí zásady vytvořené ze šablony. Zdroj: rms_sample/pfileconverter.cppProtects a file using a policy created from a template Source: rms_sample/pfileconverter.cpp

Popis: Načte se seznam šablon, které jsou přidružené uživateli, a pak se použije vybraná šablona k vytvoření zásady, která se pak použije k ochraně souboru.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);
}
}

Chrání soubor danou zásadou. Zdroj: rms_sample/pfileconverter.cppProtects a file given a policy Source: rms_sample/pfileconverter.cpp

Popis: Vytvořte pomocí dané zásady datový proud chráněného souboru a pak chraňte tento soubor.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énář: Ochrana souboru pomocí vlastní ochranyScenario: Protect a file using custom protection

Chrání soubor pomocí vlastní ochrany. Zdroj: rms_sample/mainwindow.cppProtects a file using custom protection Source: rms_sample/mainwindow.cpp

Popis: Po získání názvu souboru od uživatele, čtení certifikátů (viz MainWindow::addCertificates), shromáždění informací o právech od uživatele a nastavení zpětného volání autorizace pomocí ID klienta a adresy URL pro přesměrování se vybraný soubor chrání voláním ConvertToPFilePredefinedRights (viz následující ukázka kódu).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 convertion
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();
}

Vytvoří zásadu ochrany dávající uživateli vybraná práva. Zdroj: rms_sample/pfileconverter.cppCreates a protection policy give user selected rights Source: rms_sample/pfileconverter.cpp

Popis: Vytvořte popisovač zásad a vyplňte v něm informace o právech uživatele, pak použijte popisovač zásad k vytvoření zásady uživatele.Description: Create a policy descriptor and fill it with the user's rights information then, use the policy descriptor to create a user policy. Tato zásada se používá k ochraně vybraného souboru prostřednictvím volání ConvertToPFileUsingPolicy (viz popis v předchozí části tohoto tématu).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 – podpůrná metodaWorkerThread - a supporting method

Metoda WorkerThread() se volá ve dvou z předchozích ukázkových scénářů, Vytvoření datového proudu chráněného souboru a Chrání soubor danou zásadou, následujícím způsobem: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));

Podpůrná metoda, 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énář: Ověřování RMSScenario: RMS authentication

Následující příklady znázorňují dva různé přístupy k ověřování; získání tokenu ověřování Azure oAuth2 pomocí uživatelského rozhraní a bez něj.The following examples show two different authentication approaches; obtaining Azure Authentication oAuth2 token using UI and without UI. Získá token ověřování oAuth2 pomocí uživatelského rozhraní. Zdroj: rmsauth_sample/mainwindow.cppAcquiring oAuth2 Authentication Token with UI Source: rmsauth_sample/mainwindow.cpp

Krok 1: Vytvoření sdíleného bodu objektu rmsauth::FileCacheStep 1: Create a shared point of rmsauth::FileCache object. Popis: Můžete nastavit cestu k mezipaměti nebo použít výchozí nastavení.Description: You can set cache path or use default.

C++:C++:

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

Krok 2: Vytvoření objektu rmsauth::AuthenticationContext Popis: Určete identifikátor URI autority Azure a objekt 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);

Krok 3: Volání metody aquireToken objektu authContext a určení dalších parametrů: Popis:Step 3: Call aquireToken method of authContext object and specify next parameters: Description:

  • Požadovaný prostředek –chráněný prostředek, ke kterému chcete přistupovatRequested resource - protected resource you want to access
  • Jedinečné ID klienta – obvykle GUIDClient unique ID - usually a GUID
  • Identifikátor URI přesměrování –identifikátor URI, kterému se změní adresa po získání ověřovacího tokenuRedirection URI - the URI which will be readdressed after authentication token fetched
  • Chování výzvy ověřování – pokud nastavíte PromptBehavior::Auto, knihovna se pokusí použít mezipaměť a v případě potřeby aktualizovat tokenAuthentication prompt behavior - if you set PromptBehavior::Auto the library tries to use cache and refresh token if necessary
  • ID uživatele – uživatelské jméno zobrazované v okně výzvyUser 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”));

Krok 4: Získání tokenu přístupu z výsledku Popis: Volání metody result-> accessToken()Step 4: Get access token from result Description: Call result-> accessToken() method

Poznámka: Libovolná z metod knihovny ověřování může vyvolat výjimku rmsauth::Exception.Note Any of the authentication library methods may raise rmsauth::Exception

Získání tokenu ověřování oAuth2 bez uživatelského rozhraní Zdroj: rmsauth_sample/mainwindow.cppAcquiring oAuth2 Authentication Token without UI Source: rmsauth_sample/mainwindow.cpp

Krok 1: Vytvoření sdíleného bodu objektu rmsauth::FileCache Popis: Můžete nastavit cestu k mezipaměti nebo použít výchozí nastavení.Step 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>();

Krok 2: Vytvoření objektu UserCredential Popis: Zadejte přihlašovací jméno a heslo.Step 2:Create UserCredential object Description: Specify user login and password

C++:C++:

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

Krok 3: Vytvoření objektu rmsauth::AuthenticationContext Popis: Určete identifikátor URI autority Azure a objekt FileCache.Step 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);

Krok 4: Volání metody aquireToken objektu authContext a určení parametrů:Step 4: Call the aquireToken method of authContext and specify parameters:

  • Požadovaný prostředek –chráněný prostředek, ke kterému chcete přistupovatRequested resource - protected resource you want to access
  • Jedinečné ID klienta – obvykle GUIDClient unique ID - usually a GUID
  • Přihlašovací údaje uživatele – předejte vytvořený objektUser credentials - pass the created object

C++:C++:

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

Krok 5: Získání tokenu přístupu z výsledku Popis: Volání metody result-> accessToken()Step 5: Get access token from result Description: Call result-> accessToken() method

Poznámka: Libovolná z metod knihovny ověřování může vyvolat výjimku rmsauth::Exception.Note Any of the authentication library methods may raise rmsauth::Exception

KomentářeComments

Před přidáním komentáře se podívejte na naše pravidla organizace.Before commenting, we ask that you review our House rules.