{"id":305623,"date":"2020-06-19T15:00:55","date_gmt":"2020-06-19T15:00:55","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=305623"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2020-06-19T15:00:55","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=305623","title":{"rendered":"\u041e\u043f\u044b\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 (\u0447\u0430\u0441\u0442\u044c 4)"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/506934\/\">\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! <\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0439 \u0446\u0435\u043d\u0442\u0440 \u0441 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0438 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u043c. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0440\u0430 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u043e\u043c. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u043e\u043c \u0438\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d.<a name=\"habracut\"><\/a><\/p>\n<p>  \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u0430 \u0438 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043d\u0430 \u0432\u0430\u0448\u0435\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0435\u0449\u0435 \u0440\u0430\u0437 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 <a href=\"https:\/\/habr.com\/ru\/post\/506450\/\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u0441\u0442\u0430\u0442\u044c\u0438<\/a>.<\/p>\n<p>  \u041e\u0431\u0449\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c: <br \/>  <a href=\"https:\/\/dev.rutoken.ru\/pages\/viewpage.action?pageId=15269905\" rel=\"nofollow\">\u0412\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u0435 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u042d\u0426\u041f 2.0 \u0447\u0435\u0440\u0435\u0437 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d<\/a><br \/>  <a href=\"https:\/\/dev.rutoken.ru\/pages\/viewpage.action?pageId=57147607\" rel=\"nofollow\">\u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0412\u0435\u0440\u0441\u0438\u044f 4.4.1<\/a><\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u0447\u043d\u0435\u0442\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0442\u043e \u0443 \u0432\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441 (\u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 \u0442\u0430\u043a \u0431\u044b\u043b\u043e \u0443 \u043c\u0435\u043d\u044f). \u0427\u0442\u043e \u0437\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0442\u0430\u043a\u043e\u0439 plugin? \u0413\u0434\u0435 \u0435\u0433\u043e \u0432\u0437\u044f\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043a \u043d\u0435\u043c\u0443 \u0432\u0441\u044f\u043a\u043e\u0433\u043e \u0440\u043e\u0434\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0420\u0430\u0437\u0431\u0438\u0440\u0430\u044f\u0441\u044c \u0441 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u044f \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e <a href=\"https:\/\/dev.rutoken.ru\/pages\/viewpage.action?pageId=30113795\" rel=\"nofollow\">\u043f\u043e\u043f\u0430\u043b \u043d\u0430 \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443<\/a> <\/p>\n<p>  \u0422\u0430\u043c \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430, \u043a\u0430\u043a \u0440\u0430\u0437 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443 \u043c\u0435\u043d\u044f \u0438 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442.<br \/>  \u0422\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0443\u043f\u043e \u043d\u0430\u0434\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a \u0441\u0435\u0431\u0435, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">let rutoken = (function (my) {      let loadCallbacks = [];     let pluginMimeType = &quot;application\/x-rutoken-pki&quot;;     let extension = window[&quot;C3B7563B-BF85-45B7-88FC-7CFF1BD3C2DB&quot;];      function isFunction(obj) {         return !!(obj &amp;&amp; obj.call &amp;&amp; obj.apply);     }      function proxyMember(target, member) {         if (isFunction(target[member])) {             return function () {                 return target[member].apply(target, arguments);             };         } else {             return target[member];         }     }      function returnPromise(promise) {         return function () {             return promise;         };     }      function initialize() {         my.ready = Promise.resolve(true);         my.isExtensionInstalled = returnPromise(Promise.resolve(false));         my.isPluginInstalled = returnPromise(Promise.resolve(true));         my.loadPlugin = loadPlugin;         window.rutokenLoaded = onPluginLoaded;     }      function initializeExtension() {         let readyPromise = extension.initialize().then(function () {             return extension.isPluginInstalled();         }).then(function (result) {             my.isExtensionInstalled = returnPromise(Promise.resolve(true));             my.isPluginInstalled = proxyMember(extension, &quot;isPluginInstalled&quot;);              if (result) {                 pluginMimeType = &quot;application\/x-rutoken-plugin&quot;;                 my.loadPlugin = loadChromePlugin;             }              return true;         });          my.ready = readyPromise;     }      function initializeWithoutPlugin() {         my.ready = Promise.resolve(true);         my.isExtensionInstalled = returnPromise(Promise.resolve(false));         my.isPluginInstalled = returnPromise(Promise.resolve(false));     }      function loadPlugin() {         let obj = document.createElement(&quot;object&quot;);         obj.style.setProperty(&quot;visibility&quot;, &quot;hidden&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;width&quot;, &quot;0px&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;height&quot;, &quot;0px&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;margin&quot;, &quot;0px&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;padding&quot;, &quot;0px&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;border-style&quot;, &quot;none&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;border-width&quot;, &quot;0px&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;max-width&quot;, &quot;0px&quot;, &quot;important&quot;);         obj.style.setProperty(&quot;max-height&quot;, &quot;0px&quot;, &quot;important&quot;);          \/\/ onload callback must be set before type attribute in IE earlier than 11.         obj.innerHTML = &quot;&lt;param name='onload' value='rutokenLoaded'\/&gt;&quot;;         \/\/ Just after setting type attribute before function returns promise         \/\/ FireBreath uses onload callback to execute it with a small delay.         \/\/ So it must be valid, but it will be called a little bit later.         \/\/ In other browsers plugin will be initialized only after appending         \/\/ an element to the document.         obj.setAttribute(&quot;type&quot;, pluginMimeType);          document.body.appendChild(obj);          let promise = new Promise(function (resolve, reject) {             loadCallbacks.push(resolve);         });          return promise;     }      function loadChromePlugin() {         return extension.loadPlugin().then(function (plugin) {             return resolveObject(plugin);         }).then(function (resolvedPlugin) {             resolvedPlugin.wrapWithOldInterface = wrapNewPluginWithOldInterface;             return resolvedPlugin;         });     }      function onPluginLoaded(plugin, error) {         wrapOldPluginWithNewInterface(plugin).then(function (wrappedPlugin) {             if (loadCallbacks.length == 0) {                 throw &quot;Internal error&quot;;             }              let callback = loadCallbacks.shift();             callback(wrappedPlugin);         });     }      function resolveObject(obj) {         let resolvedObject = {};         let promises = [];          for (var m in obj) {             (function (m) {                 if (isFunction(obj[m].then)) {                     promises.push(obj[m].then(function (result) {                         return resolveObject(result).then(function (resolvedProperty) {                             if (isFunction(resolvedProperty)) {                                 resolvedObject[m] = proxyMember(obj, m);                             } else {                                 resolvedObject[m] = resolvedProperty;                             }                         });                     }));                 } else {                     resolvedObject[m] = obj[m];                 }             })(m);         }          if (promises.length == 0) {             return new Promise(function (resolve) {                 resolve(obj);             });         } else {             return Promise.all(promises).then(function () {                 return resolvedObject;             });         }     }      function wrapNewPluginWithOldInterface() {         let wrappedPlugin = {};          for (var m in this) {             if (isFunction(this[m])) {                 wrappedPlugin[m] = (function (plugin, member) {                     return function () {                         var successCallback = arguments[arguments.length - 2];                         var errorCallback = arguments[arguments.length - 1];                         var args = Array.prototype.slice.call(arguments, 0, -2);                         return member.apply(plugin, args).then(function (result) {                             successCallback(result);                         }, function (error) {                             errorCallback(error.message);                         });                     };                 })(this, this[m]);             } else {                 wrappedPlugin[m] = this[m];             }         }          return new Promise(function (resolve) {             resolve(wrappedPlugin);         });     }      function wrapOldPluginWithOldInterface() {         let unwrappedPlugin = {originalObject: this.originalObject};          for (let m in this.originalObject) {             unwrappedPlugin[m] = proxyMember(this.originalObject, m);         }          return new Promise(function (resolve) {             resolve(unwrappedPlugin);         });     }      function wrapOldPluginWithNewInterface(plugin) {         let wrappedPlugin = {             originalObject: plugin,             wrapWithOldInterface: wrapOldPluginWithOldInterface         };          for (let m in plugin) {             if (isFunction(plugin[m])) {                 wrappedPlugin[m] = (function (plugin, member) {                     return function () {                         let args = Array.prototype.slice.call(arguments);                         return new Promise(function (resolve, reject) {                             args.push(resolve, reject);                             member.apply(plugin, args);                         });                     };                 })(plugin, plugin[m]);             } else {                 wrappedPlugin[m] = plugin[m];             }         }          return new Promise(function (resolve) {             resolve(wrappedPlugin);         });     }      if (extension) {         initializeExtension();     } else if (navigator.mimeTypes &amp;&amp; navigator.mimeTypes[pluginMimeType]) {         initialize();     } else {         try {             let plugin = new ActiveXObject(&quot;Aktiv.CryptoPlugin&quot;);             initialize();         } catch (e) {             initializeWithoutPlugin();         }     }      return my; }({})); rutoken.ready     \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440\u0430 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430' \u0432 Google Chrome     .then(function () {         if (window.chrome || typeof InstallTrigger !== 'undefined') {             return rutoken.isExtensionInstalled();         } else {             console.log(&quot;\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440&quot;);             return Promise.resolve(true);         }     })     \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430     .then(function (result) {         if (result) {             console.log(&quot;\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430' \u043d\u0430\u0439\u0434\u0435\u043d\u043e&quot;);             return rutoken.isPluginInstalled();         } else {             return Promise.reject(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430'&quot;);         }     })     \/\/ \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430     .then(function (result) {         if (result) {             console.log(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0430\u0439\u0434\u0435\u043d&quot;);             return rutoken.loadPlugin();         } else {             return Promise.reject(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u041f\u043b\u0430\u0433\u0438\u043d&quot;);         }     })     \/\/\u041c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c     .then(function (plugin_) {         plugin = plugin_;         if (!plugin) {             console.log(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d&quot;);             return Promise.reject(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u041f\u043b\u0430\u0433\u0438\u043d&quot;);         } else {             console.log(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e&quot;);             return plugin.enumerateDevices()         }     }) <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434, \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Promise. \u0415\u0441\u0442\u044c <a href=\"https:\/\/learn.javascript.ru\/promise\" rel=\"nofollow\">\u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u0441\u0435 \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f Promise.<\/p>\n<p>  \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u0443\u044e \u043f\u0430\u0440\u0443 \u043d\u0430 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430.<\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0432\u043e\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a Ext Js, \u043d\u043e \u044d\u0442\u043e \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043d\u0435 \u0432\u0430\u0436\u043d\u043e. \u0423\u0432\u0435\u0440\u0435\u043d, \u0447\u0442\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0432\u0435\u0441\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0438 \u0431\u0435\u0437 \u0437\u043d\u0430\u043d\u0438\u044f Ext Js.<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e Rutoken.rutoken.ConnectToDevice<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">Ext.define('Rutoken.rutoken.ConnectToDevice', {      connectToDevice: function (rutoken) {         rutoken = rutoken.getRutoken();         return rutoken.ready             \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440\u0430 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430' \u0432 Google Chrome             .then(function () {                 if (window.chrome || typeof InstallTrigger !== 'undefined') {                     return rutoken.isExtensionInstalled();                 } else {                     console.log(&quot;\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0430\u0434\u0430\u043f\u0442\u0435\u0440 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440&quot;);                     return Promise.resolve(true);                 }             })             \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430             .then(function (result) {                 if (result) {                     console.log(&quot;\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430' \u043d\u0430\u0439\u0434\u0435\u043d\u043e&quot;);                     return rutoken.isPluginInstalled();                 } else {                     return Promise.reject(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 '\u0410\u0434\u0430\u043f\u0442\u0435\u0440 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d\u0430'&quot;);                 }             })             \/\/ \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430             .then(function (result) {                 if (result) {                     console.log(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0430\u0439\u0434\u0435\u043d&quot;);                     return rutoken.loadPlugin();                 } else {                     return Promise.reject(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u041f\u043b\u0430\u0433\u0438\u043d&quot;);                 }             })             \/\/\u041c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c             .then(function (plugin_) {                 plugin = plugin_;                 if (!plugin) {                     console.log(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041f\u043b\u0430\u0433\u0438\u043d&quot;);                     return Promise.reject(&quot;\u041d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u041f\u043b\u0430\u0433\u0438\u043d&quot;);                 } else {                     console.log(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e&quot;);                     return plugin.enumerateDevices()                 }             })             \/\/\u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u044c \u0440\u0443\u0442\u043e\u043a\u0435\u043d \u0432 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435             .then(function (devices) {                 if (devices.length &gt; 0) {                     console.log(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d&quot;);                     return Promise.resolve(devices[0]);                 } else {                     console.log(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u041d\u0415 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d&quot;);                     return Promise.reject(&quot;\u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d&quot;);                 }             })             \/\/\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0443             .then(function (device_) {                 device = device_;                 return plugin.getDeviceInfo(device, plugin.TOKEN_INFO_IS_LOGGED_IN);             })             \/\/ \u041b\u043e\u0433\u0438\u043d \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 PIN-\u043a\u043e\u0434\u043e\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e             .then(function (isLoggedIn) {                 if (isLoggedIn) {                     return Promise.resolve();                 } else {                     return plugin.login(device, &quot;12345678&quot;);                 }             })             \/\/\u0412\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0438 \u043d\u043e\u043c\u0435\u0440\u0430 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0430,             \/\/\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d \u043a \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0443             .then(function () {                 return [plugin, device];             })     } }); <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u0442\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u0430 \u043f\u043e\u0442\u043e\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e connectToDevice. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0438 \u043d\u043e\u043c\u0435\u0440\u0430 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u0430. \u0424\u0443\u043d\u043a\u0446\u0438\u044f connectToDevice \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 rutoken. \u042d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e Rutoken.rutoken.RutokenInit<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">Ext.define(&quot;Rutoken.rutoken.RutokenInit&quot;, {      config: {         rutoken: undefined,     },      constructor: function(){         let rutoken = (function (my) {              let loadCallbacks = [];             let pluginMimeType = &quot;application\/x-rutoken-pki&quot;;             let extension = window[&quot;C3B7563B-BF85-45B7-88FC-7CFF1BD3C2DB&quot;];              function isFunction(obj) {                 return !!(obj &amp;&amp; obj.call &amp;&amp; obj.apply);             }              function proxyMember(target, member) {                 if (isFunction(target[member])) {                     return function () {                         return target[member].apply(target, arguments);                     };                 } else {                     return target[member];                 }             }              function returnPromise(promise) {                 return function () {                     return promise;                 };             }              function initialize() {                 my.ready = Promise.resolve(true);                 my.isExtensionInstalled = returnPromise(Promise.resolve(false));                 my.isPluginInstalled = returnPromise(Promise.resolve(true));                 my.loadPlugin = loadPlugin;                 window.rutokenLoaded = onPluginLoaded;             }              function initializeExtension() {                 let readyPromise = extension.initialize().then(function () {                     return extension.isPluginInstalled();                 }).then(function (result) {                     my.isExtensionInstalled = returnPromise(Promise.resolve(true));                     my.isPluginInstalled = proxyMember(extension, &quot;isPluginInstalled&quot;);                      if (result) {                         pluginMimeType = &quot;application\/x-rutoken-plugin&quot;;                         my.loadPlugin = loadChromePlugin;                     }                      return true;                 });                  my.ready = readyPromise;             }              function initializeWithoutPlugin() {                 my.ready = Promise.resolve(true);                 my.isExtensionInstalled = returnPromise(Promise.resolve(false));                 my.isPluginInstalled = returnPromise(Promise.resolve(false));             }              function loadPlugin() {                 let obj = document.createElement(&quot;object&quot;);                 obj.style.setProperty(&quot;visibility&quot;, &quot;hidden&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;width&quot;, &quot;0px&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;height&quot;, &quot;0px&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;margin&quot;, &quot;0px&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;padding&quot;, &quot;0px&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;border-style&quot;, &quot;none&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;border-width&quot;, &quot;0px&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;max-width&quot;, &quot;0px&quot;, &quot;important&quot;);                 obj.style.setProperty(&quot;max-height&quot;, &quot;0px&quot;, &quot;important&quot;);                  \/\/ onload callback must be set before type attribute in IE earlier than 11.                 obj.innerHTML = &quot;&lt;param name='onload' value='rutokenLoaded'\/&gt;&quot;;                 \/\/ Just after setting type attribute before function returns promise                 \/\/ FireBreath uses onload callback to execute it with a small delay.                 \/\/ So it must be valid, but it will be called a little bit later.                 \/\/ In other browsers plugin will be initialized only after appending                 \/\/ an element to the document.                 obj.setAttribute(&quot;type&quot;, pluginMimeType);                  document.body.appendChild(obj);                  let promise = new Promise(function (resolve, reject) {                     loadCallbacks.push(resolve);                 });                  return promise;             }              function loadChromePlugin() {                 return extension.loadPlugin().then(function (plugin) {                     return resolveObject(plugin);                 }).then(function (resolvedPlugin) {                     resolvedPlugin.wrapWithOldInterface = wrapNewPluginWithOldInterface;                     return resolvedPlugin;                 });             }              function onPluginLoaded(plugin, error) {                 wrapOldPluginWithNewInterface(plugin).then(function (wrappedPlugin) {                     if (loadCallbacks.length == 0) {                         throw &quot;Internal error&quot;;                     }                      let callback = loadCallbacks.shift();                     callback(wrappedPlugin);                 });             }              function resolveObject(obj) {                 let resolvedObject = {};                 let promises = [];                  for (var m in obj) {                     (function (m) {                         if (isFunction(obj[m].then)) {                             promises.push(obj[m].then(function (result) {                                 return resolveObject(result).then(function (resolvedProperty) {                                     if (isFunction(resolvedProperty)) {                                         resolvedObject[m] = proxyMember(obj, m);                                     } else {                                         resolvedObject[m] = resolvedProperty;                                     }                                 });                             }));                         } else {                             resolvedObject[m] = obj[m];                         }                     })(m);                 }                  if (promises.length == 0) {                     return new Promise(function (resolve) {                         resolve(obj);                     });                 } else {                     return Promise.all(promises).then(function () {                         return resolvedObject;                     });                 }             }              function wrapNewPluginWithOldInterface() {                 let wrappedPlugin = {};                  for (var m in this) {                     if (isFunction(this[m])) {                         wrappedPlugin[m] = (function (plugin, member) {                             return function () {                                 var successCallback = arguments[arguments.length - 2];                                 var errorCallback = arguments[arguments.length - 1];                                 var args = Array.prototype.slice.call(arguments, 0, -2);                                 return member.apply(plugin, args).then(function (result) {                                     successCallback(result);                                 }, function (error) {                                     errorCallback(error.message);                                 });                             };                         })(this, this[m]);                     } else {                         wrappedPlugin[m] = this[m];                     }                 }                  return new Promise(function (resolve) {                     resolve(wrappedPlugin);                 });             }              function wrapOldPluginWithOldInterface() {                 let unwrappedPlugin = {originalObject: this.originalObject};                  for (let m in this.originalObject) {                     unwrappedPlugin[m] = proxyMember(this.originalObject, m);                 }                  return new Promise(function (resolve) {                     resolve(unwrappedPlugin);                 });             }              function wrapOldPluginWithNewInterface(plugin) {                 let wrappedPlugin = {                     originalObject: plugin,                     wrapWithOldInterface: wrapOldPluginWithOldInterface                 };                  for (let m in plugin) {                     if (isFunction(plugin[m])) {                         wrappedPlugin[m] = (function (plugin, member) {                             return function () {                                 let args = Array.prototype.slice.call(arguments);                                 return new Promise(function (resolve, reject) {                                     args.push(resolve, reject);                                     member.apply(plugin, args);                                 });                             };                         })(plugin, plugin[m]);                     } else {                         wrappedPlugin[m] = plugin[m];                     }                 }                  return new Promise(function (resolve) {                     resolve(wrappedPlugin);                 });             }              if (extension) {                 initializeExtension();             } else if (navigator.mimeTypes &amp;&amp; navigator.mimeTypes[pluginMimeType]) {                 initialize();             } else {                 try {                     let plugin = new ActiveXObject(&quot;Aktiv.CryptoPlugin&quot;);                     initialize();                 } catch (e) {                     initializeWithoutPlugin();                 }             }              return my;         }({}));         this.setRutoken(rutoken);     }  });<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e connectToDevice \u043a\u043b\u0430\u0441\u0441\u0430 Rutoken.rutoken.ConnectToDevice, \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u0440\u0430\u043d\u0435\u0435. \u042d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u044f \u0434\u0435\u043b\u0430\u044e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e Rutoken.rutoken.RutokenRegistration<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">Ext.define('Rutoken.rutoken.RutokenRegistration', {      registration: function (rutoken, device, scope) {         return device.connectToDevice(rutoken)             \/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438             .then(function (pluginWithDeviceIndex) {                 values = scope.lookupReference('regForm').getValues();                 plugin = pluginWithDeviceIndex[0];                 deviceIndex = pluginWithDeviceIndex[1];                 host = 'http:\/\/localhost:8080\/';                 createCrtDataPrefix = 'createCrtData';                 registrationPrefix = 'registration';             })             \/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 \u0441 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0430             .then(function () {                 return plugin.enumerateCertificates(deviceIndex, plugin.CERT_CATEGORY_USER);             })             \/\/\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043f\u0430\u0440\u044b \u043d\u0430 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0435             .then(function (crts) {                 if (crts.length &gt; 0) {                     throw &quot;Certificate already exist on rutoken&quot;;                 }             })             \/\/\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u0443\u044e \u043f\u0430\u0440\u0443 \u043d\u0430 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0435 \u043f\u043e GOST3410_2012_256             .then(function () {                 let option = {                     &quot;publicKeyAlgorithm&quot;: plugin.PUBLIC_KEY_ALGORITHM_GOST3410_2012_256                 };                 return plugin.generateKeyPair(deviceIndex, undefined, &quot;&quot;, option);             })             \/\/\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 createPkcs10 \u043d\u0430 \u0432\u044b\u0434\u0430\u0447\u0443 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430             .then(function (keyPair) {                 let subject = [                     {                         rdn: &quot;countryName&quot;,                         value: &quot;RU&quot;                     }                     , {                         rdn: &quot;stateOrProvinceName&quot;,                         value: &quot;Russia&quot;                     }                     , {                         rdn: &quot;localityName&quot;,                         value: &quot;Saint-Petersburg&quot;                     }                     , {                         rdn: &quot;streetAddress&quot;,                         value: &quot;street&quot;                     }                     , {                         rdn: &quot;organizationName&quot;,                         value: &quot;Eurica&quot;                     }                     , {                         rdn: &quot;organizationalUnitName&quot;,                         value: &quot;Rutoken&quot;                     }                     , {                         rdn: &quot;title&quot;,                         value: &quot;\u0438\u043d\u0436\u0435\u043d\u0435\u0440&quot;                     }                     , {                         rdn: &quot;commonName&quot;,                         value: `${values.name} ${values.surname}`                     }                     , {                         rdn: &quot;postalAddress&quot;,                         value: &quot;postal address&quot;                     }                     , {                         rdn: &quot;pseudonym&quot;,                         value: &quot;\u0438\u043d\u0436\u0435\u043d\u0435\u0440123&quot;                     }                     , {                         rdn: &quot;surname&quot;,                         value: `${values.surname}`                     }                     , {                         rdn: &quot;givenName&quot;,                         value: &quot;given name&quot;                     }                     , {                         rdn: &quot;emailAddress&quot;,                         value: `${values.email}`                     }                 ];                 let keyUsageVal = [                     &quot;digitalSignature&quot;                     , &quot;nonRepudiation&quot;                     , &quot;keyEncipherment&quot;                     , &quot;dataEncipherment&quot;                     , &quot;keyAgreement&quot;                     , &quot;keyCertSign&quot;                     , &quot;cRLSign&quot;                     , &quot;encipherOnly&quot;                     , &quot;decipherOnly&quot;                 ];                 let extKeyUsageVal = [                     &quot;emailProtection&quot;                     , &quot;clientAuth&quot;                     , &quot;serverAuth&quot;                     , &quot;codeSigning&quot;                     , &quot;timeStamping&quot;                     , &quot;msCodeInd&quot;                     , &quot;msCodeCom&quot;                     , &quot;msCTLSign&quot;                     , &quot;1.3.6.1.5.5.7.3.9&quot; \/\/ OSCP                     , &quot;1.2.643.2.2.34.6&quot; \/\/ CryptoPro RA user                  ];                 let certificatePolicies = [                     &quot;1.2.643.100.113.1&quot;, \/\/ \u041a\u04211                     &quot;1.2.643.100.113.2&quot;, \/\/ \u041a\u04212                     &quot;1.2.643.100.113.3&quot;, \/\/ \u041a\u04213                     &quot;1.2.643.100.113.4&quot;, \/\/ \u041a\u04121                     &quot;1.2.643.100.113.5&quot;, \/\/ \u041a\u04122                     &quot;1.2.643.100.113.6&quot;  \/\/ \u041a\u04101                 ];                 let extensions = {                     &quot;keyUsage&quot;: keyUsageVal,                     &quot;extKeyUsage&quot;: extKeyUsageVal,                     &quot;certificatePolicies&quot;: certificatePolicies                 };                 let options = {                     &quot;subjectSignTool&quot;: '\u0421\u041a\u0417\u0418 &quot;\u0420\u0423\u0422\u041e\u041a\u0415\u041d \u042d\u0426\u041f&quot;',                     &quot;hashAlgorithm&quot;: plugin.HASH_TYPE_GOST3411_12_256,                     &quot;customExtensions&quot;: [                         {                             oid: &quot;1.3.6.1.4.1.311.21.7&quot;,                             value: &quot;MA0GCCqFAwICLgAIAgEB&quot;,                             criticality: false                         }                     ],                 };                 return plugin.createPkcs10(deviceIndex, keyPair, subject, extensions, options);             })             \/\/\u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 pkcs10Message \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440             .then(function (pkcs10Request) {                 let pkcs10Message = Ext.create('Rutoken.model.RuTokenPkcs10Message');                 pkcs10Message.requestPkcs10Message = pkcs10Request;                 return pkcs10Message;             })             \/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c pkcs10Message \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430             .then(function (pkcs10Message) {                 return new Promise(function (resolve, reject) {                     Ext.Ajax.request({                         method: 'POST',                         jsonData: Ext.encode(pkcs10Message),                         url: `${host}${createCrtDataPrefix}`,                         scope: this,                         headers: {                             'accept': 'application\/json',                         },                         success: function (response) {                             let crt = Ext.decode(response.responseText);                             plugin.importCertificate(deviceIndex, crt.responseCertificateMessage, plugin.CERT_CATEGORY_USER);                             console.log('Certificate was saved successful');                             resolve(crt);                         },                         failures: function (response) {                             console.log('Failure Pkcs10 request');                             reject(response.status);                         }                     });                 });             });     } });<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044f registration \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u043e\u0432 Rutoken.rutoken.RutokenInit (rutoken), Rutoken.rutoken.ConnectToDevice (device), \u0442\u0440\u0435\u0442\u044c\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f scope \u043d\u0430 ViewController, \u0447\u0442\u043e\u0431\u044b \u0443 \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u0444\u043e\u0440\u043c\u044b (\u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u0441\u0442\u0430\u0442\u044c\u0438). <\/p>\n<p>  \u0421\u0447\u0438\u0442\u0430\u044e, \u0447\u0442\u043e \u043a\u043e\u0434 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041e\u0431\u0440\u0430\u0449\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>  \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430 \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u0443\u044e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c \u00ab\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 createPkcs10 \u043d\u0430 \u0432\u044b\u0434\u0430\u0447\u0443 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430\u00bb. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e subject. \u041e\u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u0430\u043c\u043e\u043c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0435. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u043d\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u043d\u0430 \u044d\u0442\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0438\u043d\u0430\u0447\u0435 \u0432\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. <\/p>\n<p>  \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0445\u043e\u0447\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u043f\u0430\u0440\u0430 (\u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 PUBLIC_KEY_ALGORITHM_GOST3410_2012_256), \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443 \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 options (\u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u00abhashAlgorithm\u00bb: plugin.HASH_TYPE_GOST3411_12_256). \u0415\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043f\u0430\u0440\u044b, \u0442\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. <\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0430, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0438 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u0430\u043c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u0420\u0443\u0442\u043e\u043a\u0435\u043d.<\/p>\n<p>  \u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u041c\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u043b\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u043d\u0430 \u0441\u0432\u043e\u0435\u043c \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u0435 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u0441 \u043d\u0435\u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043f\u0430\u0440\u043e\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0439 \u0446\u0435\u043d\u0442\u0440 \u0437\u043d\u0430\u0435\u0442 \u043e \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0441\u0430\u043c \u0435\u0433\u043e \u0432\u044b\u0434\u0430\u043b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 <a href=\"https:\/\/habr.com\/ru\/post\/507166\/\">\u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>.<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043f\u0438\u0441\u0430\u043d <a href=\"https:\/\/habr.com\/ru\/post\/506450\/\">\u0442\u0443\u0442<\/a>.<\/p>\n<p>  \u0414\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043d\u043e\u0439 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u043a\u043b\u0430\u0441\u0441 Rutoken.rutoken.RutokenAuthorization:<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e Rutoken.rutoken.RutokenAuthorization<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\"> Ext.define('Rutoken.rutoken.RutokenAuthorization', {      reference: &quot;ruTokenAuthorization&quot;,      authorization: function (rutoken, device, scope) {         return device.connectToDevice(rutoken)             \/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438             .then(function (pluginWithDeviceIndex) {                 plugin = pluginWithDeviceIndex[0];                 deviceIndex = pluginWithDeviceIndex[1];                 values = scope.lookupReference('authForm').getValues();                 host = 'http:\/\/localhost:8080\/';                 prefixSalt = 'get-authentication-salt';                 prefixAuthentication = 'authentication';                 prefixLogin = 'login';             })             \/\/\u0414\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 salt             .then(function () {                 return new Promise(function (resolve, reject) {                     Ext.Ajax.request({                         method: 'POST',                         jsonData: &quot;&quot;,                         url: `${host}${prefixSalt}`,                         scope: this,                         headers: {                             'accept': 'application\/json',                         },                         success: function (response) {                             console.log(`Success ${host}${prefixSalt} request`);                             resolve(Ext.decode(response.responseText));                         },                         failures: function (response) {                             console.log(`Failure ${host}${prefixSalt} request`);                             reject(response.status);                         }                     });                 });             })             .then(function (responseData) {                 salt = responseData;             })             \/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0432 \u0441 \u0440\u0443\u0442\u043e\u043a\u0435\u043d\u0430             .then(function () {                 return plugin.enumerateCertificates(deviceIndex, plugin.CERT_CATEGORY_USER);             })             \/\/\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442.             \/\/\u041d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u043a \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043f\u0430\u0440\u0435.             .then(function (crts) {                 return plugin.authenticate(deviceIndex, crts[0], salt.salt);             })             \/\/\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c             .then(function (auth) {                 auth = &quot;-----BEGIN CMS-----\\n&quot; + auth + &quot;-----END CMS-----&quot;;                 return auth;             })             \/\/\u0424\u043e\u0440\u043c\u0438\u0440\u0443\u043c \u043e\u0431\u044a\u0435\u043a\u0442 authenticateMessage \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440             .then(function (auth) {                 let authenticateMessage = Ext.create(&quot;Rutoken.model.RuTokenAuthenticateMessage&quot;);                 authenticateMessage.authenticateMessage = auth;                 return authenticateMessage;             })             \/\/\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 authenticateMessage \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440             .then(function (authenticateMessage) {                 return new Promise(function (resolve, reject) {                     Ext.Ajax.request({                         method: 'POST',                         jsonData: Ext.encode(authenticateMessage),                         url: `${host}${prefixAuthentication}`,                         scope: this,                         headers: {                             'accept': 'application\/json',                         },                         success: function (response) {                             console.log(`Success ${host}${prefixAuthentication} request`);                             resolve(Ext.decode(response.responseText).authorizationSuccess);                         },                         failures: function (response) {                             console.log(`Failure ${host}${prefixAuthentication} request`);                             reject(response.status);                         }                     });                 });             });     }, }); <\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442 authorizationSuccess \u0441 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0448\u043b\u0430 \u043b\u0438 \u043d\u0430\u0448\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043b\u0438 \u043d\u0435\u0442. <\/p>\n<p>  \u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0443 <a href=\"https:\/\/aktivco.github.io\/rutoken-plugin-demo\/\" rel=\"nofollow\">\u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0430.<\/p>\n<p>  \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u043e\u0442 \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439 \u0431\u044b\u043b \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0434\u043b\u044f \u0432\u0430\u0441, \u0436\u0435\u043b\u0430\u044e \u0443\u0434\u0430\u0447\u0438 \u0438 \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435!<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/506934\/\"> https:\/\/habr.com\/ru\/post\/506934\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/506934\/\">\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c! <\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0438\u0439 \u0446\u0435\u043d\u0442\u0440 \u0441 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0438 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u043c. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0440\u0430 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u043e\u043c. \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441 \u0420\u0443\u0442\u043e\u043a\u0435\u043d\u043e\u043c \u0438\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0420\u0443\u0442\u043e\u043a\u0435\u043d \u043f\u043b\u0430\u0433\u0438\u043d.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-305623","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/305623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=305623"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/305623\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=305623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=305623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=305623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}