<script> // ПРИМЕР ДЛЯ GOOGLE CHROME // // Так как все функции Плагина выполняются в отдельных потоках, не заставляя браузер ждать выполнения операций, его интерфейс постороен на промисах. // Промисы - это способ организации асинхронного кода. // Все функции Плагина возвращают промисы, хотя текущая документация еще не содержит это. // Универсальный метод добавления обработчиков: // promise.then(onFulfilled, onRejected) // onFulfilled - функция, которая будет вызвана с результатом при успешном выполнении асинхронной функции. // onRejected - функция, которая будет вызвана с ошибкой при ошибке выполнения асинхроннной функции. // ПРИМЕР ПОДПИСАНИЯ ДАННЫХ С ИСПОЛЬЗУЮЯ РУТОКЕН ПЛАГИН // // Для запуска примера в настройках Адаптера Рутокен Плагин надо поставить флажок "Разрешить открывать локальные файлы по ссылкам" var plugin; window.onload = function () { rutoken.ready // Проверка установки расширение 'Адаптера Рутокен Плагина' в Google Chrome .then( function () { if (window.chrome || typeof InstallTrigger !== 'undefined') { return rutoken.isExtensionInstalled(); } else { return Promise.resolve(true); } }) // Проверка установки Рутокен Плагина .then( function (result) { if (result) { return rutoken.isPluginInstalled(); } else { return Promise.reject("Не удаётся найти расширение 'Адаптер Рутокен Плагина'"); } }) // Загрузка плагина .then( function (result) { if (result) { return rutoken.loadPlugin(); } else { return Promise.reject("Не удаётся найти Плагин"); } }) //Можно начинать работать с плагином .then( function (result) { if (!result) { return Promise.reject("Не удаётся загрузить Плагин"); } else { plugin = result; return Promise.resolve(); } }) .then(function () { document.getElementById("pluginStatus").innerHTML = "<pre>Плагин загрузился</pre>"; }, function (msg) { document.getElementById("pluginStatus").innerHTML = "<pre>" + msg + "</pre>"; }); } // Фунцкия обратоки ошибок от Плагина // Загрузите нужную версию документации по ссылке https://dev.rutoken.ru/display/PUB/RutokenPluginDoc // В разделе CLASS: ERRORCODES описаны все возможные ошибки function handleError(reason) { var errorCodes = plugin.errorCodes; var isErrCode = isNaN(parseInt(reason.message)); switch (parseInt(reason.message)) { case errorCodes.PIN_INCORRECT: alert("Неверный PIN"); break; default: alert("Неизвестная ошибка"); } } var rutokenHandle, certHandle; sign = function () { // Получение текста для подписи var textToSign = document.getElementById("textToSign").value; if (textToSign.length == 0) { alert("Не хватает текста для подписи"); return; } // Перебор подключенных Рутокенов plugin.enumerateDevices() .then( function (devices) { if (devices.length > 0) { return Promise.resolve(devices[0]); } else { return Promise.reject("Рутокен не обнаружен"); } }) // Проверка залогиненности .then( function (firstDevice) { rutokenHandle = firstDevice; return plugin.getDeviceInfo(rutokenHandle, plugin.TOKEN_INFO_IS_LOGGED_IN); }) // Логин на первый токен в списке устройств PIN-кодом по умолчанию .then( function (isLoggedIn) { if (isLoggedIn) { return Promise.resolve(); } else { return plugin.login(rutokenHandle, "12345678"); } }) // Перебор пользовательских сертификатов на токене .then( function () { return plugin.enumerateCertificates(rutokenHandle, plugin.CERT_CATEGORY_USER); }) // Подписание данных из текстового поля на первом найденом сертификате .then( function (certs) { if (certs.length > 0) { certHandle = certs[0]; return plugin.sign(rutokenHandle, certHandle, textToSign, false, {}); } else { return Promise.reject("Сертификат на Рутокен не обнаружен"); } }) // Отображение подписанных данных в формате CMS .then( function (cms) { alert(cms); }) // Закрытие сессии .then( function () { plugin.logout(rutokenHandle); }, handleError); } </script> <pre> - - - - - - - - - - - - - - - - подготовьте Рутокен- - - - - - - - - - - - - - - - - - - - - - | | Для работы этой странички требуется ключевая пара и сертификат. <a href="http://ra.rutoken.ru">Создайте их на ra.rutoken.ru</a> | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </pre> <div id="pluginStatus"><pre>Загрузка Плагина...</pre></div> <textarea rows="10" cols="95" id="textToSign" placeholder="Введите текст для подписи"></textarea><br/> <button id="signButton" onclick="sign()" style="display: block; background: none; border: 4px solid black; font-family: monospace; width: 20em; height: 3em; text-align: center; cursor: pointer;">Подписать текст</button> <!-- вспомогательный скрипт-обертка над Пагином --> <script> var rutoken = (function (my) { var loadCallbacks = []; var pluginMimeType = "application/x-rutoken-pki"; var extension = window["C3B7563B-BF85-45B7-88FC-7CFF1BD3C2DB"]; function isFunction (obj) { return !!(obj && obj.call && 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() { var readyPromise = extension.initialize().then(function () { return extension.isPluginInstalled(); }).then(function (result) { my.isExtensionInstalled = returnPromise(Promise.resolve(true)); my.isPluginInstalled = proxyMember(extension, "isPluginInstalled"); if (result) { pluginMimeType = "application/x-rutoken-plugin"; 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 () { var obj = document.createElement("object"); obj.style.setProperty("visibility", "hidden", "important"); obj.style.setProperty("width", "0px", "important"); obj.style.setProperty("height", "0px", "important"); obj.style.setProperty("margin", "0px", "important"); obj.style.setProperty("padding", "0px", "important"); obj.style.setProperty("border-style", "none", "important"); obj.style.setProperty("border-width", "0px", "important"); obj.style.setProperty("max-width", "0px", "important"); obj.style.setProperty("max-height", "0px", "important"); // onload callback must be set before type attribute in IE earlier than 11. obj.innerHTML = "<param name='onload' value='rutokenLoaded'/>"; // 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("type", pluginMimeType); document.body.appendChild(obj); var 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 "Internal error"; } var callback = loadCallbacks.shift(); callback(wrappedPlugin); }); } function resolveObject (obj) { var resolvedObject = {}; var 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 () { var 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 () { var unwrappedPlugin = { originalObject: this.originalObject }; for (var m in this.originalObject) { unwrappedPlugin[m] = proxyMember(this.originalObject, m); } return new Promise(function (resolve) { resolve(unwrappedPlugin); }); } function wrapOldPluginWithNewInterface (plugin) { var wrappedPlugin = { originalObject: plugin, wrapWithOldInterface: wrapOldPluginWithOldInterface }; for (var m in plugin) { if (isFunction(plugin[m])) { wrappedPlugin[m] = (function (plugin, member) { return function() { var 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 && navigator.mimeTypes[pluginMimeType]) { initialize(); } else { try { var plugin = new ActiveXObject("Aktiv.CryptoPlugin"); initialize(); } catch (e) { initializeWithoutPlugin(); } } return my; }(rutoken || {})); if (typeof module !== 'undefined') { module.exports = rutoken; } </script> |
<!DOCTYPE html> <script type="text/javascript" src="rutoken.js"></script> <title>Rutoken Plugin Tutorial</title> |
// ПРИМЕР ДЛЯ GOOGLE CHROME // Все функции Плагина возвращают промисы, хотя текущая документация еще не содержит это. // Универсальный метод добавления обработчиков: // ПРИМЕР ПОДПИСАНИЯ ДАННЫХ С ИСПОЛЬЗУЮЯ РУТОКЕН ПЛАГИН // Проверка установки расширение 'Адаптера Рутокен Плагина' в Google Chrome // Проверка установки Рутокен Плагина // Загрузка плагина //Можно начинать работать с плагином .then(function () {
switch (parseInt(reason.message)) { var rutokenHandle, certHandle; // Перебор подключенных Рутокенов .then( function (devices) { // Проверка залогиненности // Логин на первый токен в списке устройств PIN-кодом по умолчанию // Перебор пользовательских сертификатов на токене // Подписание данных из текстового поля на первом найденом сертификате // Отображение подписанных данных в формате CMS // Закрытие сессии |
var rutoken = (function (my) { function isFunction (obj) { function proxyMember (target, member) { function returnPromise (promise) { function initialize () { function initializeExtension() { if (result) { return true; my.ready = readyPromise; function initializeWithoutPlugin () { function loadPlugin () { // onload callback must be set before type attribute in IE earlier than 11. document.body.appendChild(obj); var promise = new Promise(function (resolve, reject) { return promise; function loadChromePlugin () { function onPluginLoaded (plugin, error) { var callback = loadCallbacks.shift(); function resolveObject (obj) { for (var m in obj) { if (promises.length == 0) { function wrapNewPluginWithOldInterface () { for (var m in this) { return new Promise(function (resolve) { function wrapOldPluginWithOldInterface () { return new Promise(function (resolve) { function wrapOldPluginWithNewInterface (plugin) { for (var m in plugin) { return new Promise(function (resolve) { if (extension) { return my; if (typeof module !== 'undefined') {
|