Hesla si musíte ukládat, protože nevíte, jak s nimi zacházejí ostatní

21. 5. 2021
Doba čtení: 7 minut

Sdílet

Autor: Depositphotos
Práce s hesly je neustále opakované téma, protože je to téma důležité. Pokud budete s hesly zacházet špatně, přijdete o identitu nebo peníze. Správce hesel je dnes základní součástí vaší bezpečnosti.

Když vás požádám, abyste mi řekli své heslo, uděláte to? Určitě ne. Když vás o to požádá nějaká neznámá stránka na internetu, zadáte ho tam? Doufám, že ne. Pokud vás ale o to požádá nová skvělá a užitečná služba během registrace? Většina lidí to udělá a své heslo tam zadá.

Dvě třetiny lidí používají jedno heslo na více účtech, nebo dokonce na všech. Jinými slovy to znamená, že pokud je někdo na internetu prostřednictvím registračního formuláře požádá o vložení hesla, klidně tam napíšou své hlavní a jediné heslo, které zároveň používají do bankovnictví, e-mailu, svých sociálních sítí a podobně. Na počkání tak své heslo prozrazují prakticky komukoliv, kdo se zeptá.

Nedržte hesla v hlavě

Když své heslo zadáte do nějaké služby, ztrácíte nad ním kontrolu. Netušíte, jak daná služba s hesly pracuje, zda je správně ukládá a nevyzradí nikomu dalšímu. Naprosto běžně se stává, že se darebáci dostanou k uživatelské databázi, zkopírují z ní data a vystaví na internetu. Dropbox, Mall.cz, hotelová síť Mariott a mnoho dalších už přišlo o hesla svých uživatelů. Děje se to dnes a denně, dokonce i bankám.

Pokud se chcete podívat, jak jsou na tom vaše hesla, navštivte web Have I Been Pwned, který sbírá uniklé databáze hesel a nechává v nich uživatele hledat. Zadáte e-mail a hned víte, odkud vaše hesla už unikla. Možná budete překvapeni, kolikrát už se vaše heslo dostalo na internet.

Právě proto, že nemůžeme ohlídat bezpečnost stovek námi používaných služeb, musíme zajistit co možná nejvyšší míru bezpečnosti u sebe. Musíme počítat s tím, že z některé naší oblíbené služby heslo unikne. Statistiky jsou neúprosné: dřív nebo později se to stane každému uživateli.

Jediným řešením je mít pro každou službu úplně jiné heslo, jehož únik neohrozí bezpečnost našich dalších účtů. Heslo má být spotřebním zbožím, které se dá kdykoliv vyměnit, pokud nastane problém. Ale tohle heslo mám od třetí třídy! Žádnou nostalgii, heslo je technický identifikátor. Není to dopis od naší první lásky. Nesmíme na něm lpět.

Pokud tedy chceme mít pro stovky služeb stovky různých hesel, musíme si je zapsat. Zapomeňte na to, že vám to dřív někdo zakazoval. Neměl pravdu. Nemáme mozek uzpůsobený tomu, abychom si zapamatovali byť desítky různých hesel. Natož stovky. Heslo musí být někde napsané, aby bylo dobré, a hlavně unikátní. Můžete použít notýsek, ale mnohem lepší je správce hesel.

Mýty o správcích hesel

Pod každým článkem o správcích hesel se objeví stejná diskuse, ve které se pořád dokolečka omílají stejné mýty a nesmysly o správcích hesel. Abychom si to odbyli, vysvětlíme si to rovnou v článku. Místo zbytečné diskuse se budete moci jít třeba projít ven.

Není nebezpečné mít hesla na jednom místě? Máte svá hesla na jednom místě, ať chcete, nebo ne. Procházejí v každém případě vaším počítačem. Buď je tam zadáváte stále dokola pomocí klávesnice, nebo je máte bezpečně uložené v šifrovaném správci. Z hlediska úspěšného útočníka v tom není rozdíl, pokud vám počítač napadne, stejně se k heslům dostane. V praxi je ale pořád lepší mít hesla na jednom počítači pod naší kontrolou než mít jedno superheslo, které krouží po stovkách služeb po celém internetu a má ho bůhvíkdo.

Nemůže se někdo k obsahu mého správce dostat? Správce hesel nemusí automaticky znamenat synchronizaci po internetu. Pravda je, že moderní nástroje to kvůli pohodlí uživatelů nabízejí. Zásadní je, že po internetu putují jen šifrovaná data, takže útočník se k obsahu komunikace nedostane. Je to stejně bezpečné jako komunikace od bankomatu směrem do banky. Pokud by se tohle šifrování někomu podařilo prolomit, měli bychom větší problém než vyzrazení hesel.

Co když ale někdo opravdu hackne službu na ukládání hesel? To se dokonce už stalo. Někomu se podařilo dostat do databáze služby LastPass a zkopírovat nějaké informace. Protože jsou ale hesla šifrovaná, nemá šanci se k nim útočník dostat. Získal jen e-mailové adresy uživatelů, ale ne jejich citlivá data. Vše je vymyšleno tak, že se na servery ukládají jen šifrované podoby, které jsou k ničemu. Musí se stáhnout do klienta a teprve ten je u sebe v bezpečném prostoru dešifruje a umožní je uživateli použít.

Dokáže mě správce hesel ochránit před všemi útoky? Správce hesel není kouzelný klobouk a neumí všechno. Dramaticky ale dokáže snížit riziko napadení uživatele. Nic není nikdy stoprocentní, ale celá bezpečnost se zabývá analýzou a snižováním rizik. Proti škodám způsobeným únikem hesla se dá bránit velmi účinně právě tím, že budeme mít unikátní heslo pro každou službu.

Není jednodušší si zapamatovat heslo než použít nějaký program? Můžete si zapamatovat jedno složité heslo nebo třeba tři, to ale rozhodně nestačí. Až se tohle heslo objeví na internetu, budete mít velmi vážný bezpečnostní problém. Nedělejte to, zacházejte s hesly bezpečně. Nastavit správce hesel je velmi jednoduché a můžete si do něj pak ukládat spoustu dalších podrobností, jako jsou čísla karet, rodná čísla, hesla k Wi-Fi a další citlivé informace. Je to užitečný pomocník.

Co se službou, která potřebuje konkrétní podobu hesla? Některé služby vyžadují, aby heslo mělo konkrétní parametry. Například osm písmen, tři číslice a dva speciální znaky uprostřed. Pro správce hesel to ale není problém, není nutné hesla vždy generovat úplně náhodně, ale lze ukládat i libovolná hesla, která odpovídají takovým požadavkům.

Proč je správce hesel užitečný

Úlohou správce je generovat za nás a udržovat velkou sadu náhodných hesel pro mnoho služeb, které používáme. Určitě to znáte: šmarijápanno, další heslo, co si musím vymyslet! Se správcem hesel je to hračka: vygenerovat, uložit, hotovo. Při úniku hesla jen pokrčíte rameny a v klidu zopakujete stejné kroky: vygenerovat, uložit, hotovo.

Je tu ale ještě další obrovská výhoda, kterou vám správce hesel přináší: odolnost proti phishingu. Pokud si útočník zaregistruje překlepovou doménu, která je velmi podobná skutečné doméně vaší banky, nemusíte si všimnout rozdílu. Pokud skutečně pokaždé podrobně adresu nezkoumáte, může vám útočník zobrazit svůj vlastní přihlašovací formulář. Pokud držíte heslo v hlavě, je velká pravděpodobnost, že ho do podvržené stránky zapíšete.

Správce hesel to ale neudělá. Ten si totiž pamatuje kombinaci adresy, uživatelského jména a hesla. Pokud narazí na neznámou stránku, heslo pro ni nenabídne. Nemá jaké, tenhle web přeci nezná. Vy tedy bezmyšlenkovitě heslo neodešlete někomu cizímu, protože vás před tím dobrý správce hesel ochrání.

Jakého správce hesel použít?

Správců hesel existuje celá řada a vy teď možná dumáte, jakého vlastně máte použít a jaké jsou v nich rozdíly. Řekneme si tedy o těch nejběžnějších, které můžete začít používat teď hned.

Webové prohlížeče: Všechny moderní webové prohlížeče (Chrome, Firefox, Safari a další) umožňují generovat a ukládat na webových stránkách hesla. Jejich výhodou je, že jsou rovnou po ruce a můžete je okamžitě začít používat. Nevýhodou zase je, že nejsou tak univerzální, nedovolují ukládání dalších informací a nenabízejí další pokročilejší funkce, jako třeba sdílení konkrétních hesel mezi uživateli. Pokud ale tyhle věci nepotřebujete, směle do nich.

1Password: Správce hesel, který prochází pravidelným bezpečnostním auditem kódu. Můžete si jej nainstalovat na počítač, do mobilu nebo jako rozšíření do prohlížeče. Má více než 15 milionů uživatelů a nabízí řadu pokročilých funkcí pro týmy a firmy. Jedná se o placenou službu, za základní variantu zaplatíte asi stokorunu měsíčně. Vyzkoušet si jej můžete na dva týdny zdarma. (web)

BitWarden: Svobodný otevřený správce hesel, který můžete používat úplně zadarmo. Také prochází bezpečnostními audity a certifikacemi, takže jde o velmi bezpečné řešení. Volitelně je možné zaplatit za službu, která nabízí synchronizaci mezi více zařízeními, sdílení hesel mezi uživateli nebo třeba varování před úniky hesel z různých služeb. Pokud máte svůj server, můžete si synchronizaci zařídit u sebe a neplatit nic navíc. (web)

bitcoin_smenarna

KeePass: Svobodný správce hesel, který ukládá veškerá svá data do šifrovaného souboru na disku. Hodí se, pokud si chcete vše řídit sami a nechcete využívat žádnou připravenou synchronizační službu. Prošel také bezpečnostním auditem, který jej označil za stejně vhodný jako jiná srovnatelná řešení. Jde o otevřený nástroj, takže existuje celá řada alternativních implementací pro všechny možné platformy. (web)

Správců hesel existují desítky, jako rozcestník vám může pomoci velký přehled na Wikipedii. Liší se v nabízených službách, otevřenosti kódu, možnostech synchronizace a třeba také v podpoře operačních systémů. To hlavní mají ale vždy společné: umožňují pracovat s hesly mnohem bezpečněji, než jak to umí vaše hlava.

Autor článku

Petr Krčmář pracuje jako šéfredaktor serveru Root.cz. Studoval počítače a média, takže je rozpolcen mezi dva obory. Snaží se dělat obojí, jak nejlépe umí.

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »