2012-02-02

Blockera besökare på Blogger/Blogspot

Googles bloggverktyg Blogger/Blogspot har inte någon blockeringsfunktion för enskilda användare. Det är allt eller inget genom inställningen under Inställningar - Basfunktioner - Tillstånd - Bloggläsare. Rättighetern som finns tillgängliga är Alla, Endast bloggskribenter och Enbart de här läsarna. Det fungerar bra för bloggar man vill hålla privata till ett begränsat antal läsare, men fungerar inte alls bra när man vill blockera några få.

Går det att blockera enskilda användare även fast det saknas stöd i Blogger?
Ja, med hjälp av lite javascript och klipp och klistra så löser man det genom att blockera vissa IP-adresser eller host-namn.
Det går hyffsat lätt att ta sig förbi skyddet genom att använda en proxy, men jag tror ändå att ett skydd byggt med javascript hindrar majoriteten av de man vill slippa. En proxy kräver ändå ett antal extrasteg och ofta att man betalar för tjänsten.

Hur gör man?
Jag har hämtat inspiration från följande sidor:
http://www.javascriptkit.com/script/script2/blockip.shtml
http://stackoverflow.com/questions/102605/can-i-lookup-the-ip-address-of-a-hostname-from-javascript

Gå till Blogger (kontrollpanelen för bloggarna på Blogspot) och klicka på din blogg.
Gå till menyvalet Layout och klicka på "Lägg till Gadget".
Rulla ner till "HTML/JavaScript" och tryck på +-knappen för att lägga till den.
Skriv ingen titel utan klistra endast in följande i rutan för Innehåll:
http://pastie.org/3301106 (Klicka på länken och hämta koden från Pastie)

Ändra följande rad och fyll i de IP-adresser du vill blockera (exempel på 2 olika adresser):
var bannedIps=["23.23.23.23", "11.11.11"]
Skriptet matchar början på en IP-adress så för att blockera alla IP-adresser som börjar med 23.23.23 skriver du följande:
var bannedIps=["23.23.23"]
Det går även att matcha hostname om du kör din egen tjänst för att slå upp IP-adresser och hostname. Blockera hostname genom att ändra följande rad:
var bannedHosts=["host1.se", "host2.se"];
Tryck slutligen på Spara
Det läggs nu till en gadget som heter "HTML/Javascript" och kommer skicka alla besökare med de inmatade IP-adresserna till http://www.google.com
Om du vill ändra adress till var de skickas så ändrar du adressen i följande rad:
window.location.replace("http://www.google.com");

Vad gör skriptet?
Den börjar med att se till att det garanterat finns en funktion för att hämta ut alla element via ett klassnamn. Vissa webbläsare har inte metoden getElementsByClassName.
Sedan kommer själva blockeringsfunktionen som matchar en lista med blockerade IP-adresser mot den IP-adress som skickades till funktionen. Om den får en träff så döljer den alla div:ar som har klassen "content" och skickar sedan vidare användaren till http://www.google.com
Därefter kommer en callback-funktion som används för att ta emot svaret från tjänsten som tar fram IP-adressen. Svaret är i json så den tar ut IP-adressen ur svaret och skickar den vidare till blockeringsfunktionen.
Allra sist kommer anropet till tjänsten som kollar upp IP-adressen på besökaren och genom att ange en callback-parameter så triggar den min callback-funktion som slutligen triggar blockeringsfunktionen.

Kända problem
Tjänsten för att kolla upp IP-adresser och sedan anropa min callback-funktion blir lätt överbelastad eftersom många använder den. Det som händer är att tjänsten ligger på Google App Engine och utvecklaren kör bara gratisvarianten vilket bara tillåter ett visst antal requester per dygn. När det inträffar så kommer blockeringsfunktionen att sluta fungera tills tjänsten får ny quota.

Min lösning på det är att tillhandahålla min egen tjänst skriven i PHP. Den är inte publik och om jag släpper URL:en dit så riskerar den att bli överbelastad. Det är enkelt att skapa det själv med följande PHP-kod:
http://pastie.org/3301306 (Klicka på länken och hämta koden från Pastie)

PHP-skriptet skickar först ut headers som anger att det är en response i JSON och att inget ska cachas. Sedan plockar det ut IP-adress, hostname och eventuell callback-parameter och skriver ut det i JSON-format. Om en callback-parameter är angiven så läggs JSON-svaret som ett argument till angiven funktion. Det gör att när man bäddar in skriptet i en webbsida så kommer den automatiskt anropa callback-funktionen.