Pokazywanie postów oznaczonych etykietą tutorial. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą tutorial. Pokaż wszystkie posty

wtorek, 30 października 2012

MongoDB development replication-set how-to


I will describe how to configure and run a MongoDB (v2.0.6) replication set consisting of 3 nodes on localhost machine. For more informations (architecture, voting, etc.) please refer to http://www.mongodb.org/display/DOCS/Replica+Sets


1. Create necessary directories for each node

sudo mkdir -p /srv/mongodb/rs0-0
sudo mkdir -p /srv/mongodb/rs0-1
sudo mkdir -p /srv/mongodb/rs0-2


2. Create configuration files for each node

sudo touch /srv/mongodb/rs0-0/node0.conf
sudo touch /srv/mongodb/rs0-1/node1.conf
sudo touch /srv/mongodb/rs0-2/node2.conf


3. Edit each configuration file respectively:


3.1 node0.conf
# mongo.node0.conf
replSet=r0
logpath=node0.log
port = 27017
logappend=true
dbpath=/srv/mongodb/rs0-0
fork = true
rest = true

3.2 node1.conf
# mongo.node1.conf
replSet=r0
logpath=node1.log
port = 27018
logappend=true
dbpath=/srv/mongodb/rs0-1
fork = true
rest = true

3.3 node2.conf
# mongo.node2.conf
replSet=r0
logpath=node2.log
port = 27019
logappend=true
dbpath=/srv/mongodb/rs0-2
fork = true
rest = true

We are creating 3 nodes, each of them works on different port (27017, 27018, 27019), in the same replication set (r0), as a process (fork) with enabled logging and rest interface.


4. Create configuration for replication set

When initalizing a replication set all machines need to know about each others. I would create a text file in json style in main directory and later on copy it's contents to mongo console.

sudo touch /srv/mongodb/config

config = {_id: "r0", 
        members:[
                {_id: 0, host: '127.0.0.1:27017'},
                {_id: 1, host: '127.0.0.1:27018'},
                {_id: 2, host: '127.0.0.1:27019', priority: 0, slaveDelay: 60},
                ]
};

We are creating a new set (named r0) with an array of members. Notice that machine with id 2 works with delay (each operation will be executed with 60 seconds delay) therefore it cannot be elected as primary (priority to zero, necessary condition).


5. Run all nodes

Open 4 terminal windows. First three will represent nodes, the last one will be a mongo client used for establishing connections.

Terminals 1-3 (in directory /srv/mongodb/rs0-x):

sudo mongod -f node[x].conf
tail -f node[x].log

(where [x] stands for node number)


6. Connect to any node and initialize a replication set

In the last terminal type:

mongo localhost:27018 (port could be 27017 or 27019, it doesn't matter right now)

Copy and paste the contents of /srv/mongodb/config file formerly created - it will now become a json-style variable.

Then in console type:

> rs.initiate(config);

As an output you ought see:

{
"info" : "Config now saved locally.  Should come online in about a minute.",
"ok" : 1
}

From now, nodes started communicating to each other. You can see current state of the set by typing:

> rs.status()

{
"set" : "r0",
"date" : ISODate("2012-10-30T15:30:20Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 109,
"optime" : {
"t" : 1351610907000,
"i" : 1
},
"optimeDate" : ISODate("2012-10-30T15:28:27Z"),
"lastHeartbeat" : ISODate("2012-10-30T15:30:19Z"),
"pingMs" : 0
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"optime" : {
"t" : 1351610907000,
"i" : 1
},
"optimeDate" : ISODate("2012-10-30T15:28:27Z"),
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 111,
"optime" : {
"t" : 1351610907000,
"i" : 1
},
"optimeDate" : ISODate("2012-10-30T15:28:27Z"),
"lastHeartbeat" : ISODate("2012-10-30T15:30:19Z"),
"pingMs" : 0
}
],
"ok" : 1
}

We can see that all machines are up and in good condition. Node with id was chosen as a PRIMARY node (write/read permissions), while the others are in SECONDARY state.


7. Extras

7.1 Experiments
Experiment how nodes behave in certain situations:
- insert data into primary node, reconnect to other machine and check if it is still available
- insert data on secondary machine (tip. use slaveOk function) and check if it is available to other nodes
- break one node (ie. a safe way to disconnect slave node is to connect to that node and type

use admin
db.shutdownServer()

then reconnect to your primary node, load some data, after a while bring broken node back to live and try to observe the process of automatic recovery (rs.status())
- insert a large set of data, disconnect one node, ensure an index on some field (might take time), reconnect this node as a primary, than perform recovery

7.2 Web status
You can check current status of your set using web browser. Just type http://localhost:28017/_replSet

7.3 Production
Remeber that this configuration is for learning puroposes only. When using it on production always assure that each node is on different machine (or in cloud)

poniedziałek, 27 czerwca 2011

Tworzenie aplikacji na Facebooka w PHP wykorzystując Graph API w praktyce.

Cel ćwiczenia: zapoznanie się z zasadą pobierania danych użytkownika za pomocą Graph API.

Opis: Zaprojektować system autoryzujący użytkownika, wyświetlający jego zdjęcie, imię, nazwisko, miejsce zamieszkania oraz polubione rzeczy.

Efekt finalny przedstawiono na zrzucie ekranu.


Cały proces podzielimy na trzy części. W pierwszej zaprojektujemy na lokalnym komputerze szkic witryny z wykorzystaniem elementów CSS3, a w drugiej rozbudujemy autoryzujący skrypt utworzony w tym poście, aby spełniał założenia zadania.W ostatniej scalimy ze sobą dwie pierwsze uzyskując ostateczną aplikację.

1. Projekt HTML

1.1 Wizualny schemat strony.
Przed przystąpieniem do zadania warto naszkicować sobie na kartce papieru schemat witryny i oznaczyć poszczególne divy. Ja zrobiłem to w ten sposób:
Sekcja #frame zawiera w sobie wszystkie elementy. Jej szerokość jest 10px mniejsza niż szerokość jaką daje nam okno iFrame Facebooka (760px). Wewnątrz mamy dwa większe kontenery - #topPanel i #mainArea. Pierwszy zawiera zdjęcie użytkownika, jego imię i nazwisko oraz miasto w którym aktualnie się znajduje. Drugi składa się ze stałego tekstu oraz pola #userLikes sformatowanego tak, by wyświetlał dane w trzech kolumnach.

1.2 Szkic w kodzie HTML
Kod HTML, zawierający te wszystkie elementy może wyglądać np tak:
<div id="frame">
 <div id="topPanel">
   <div id="photoDiv">
   </div>
   
   <div id="nameDiv">
   </div>
   
   <div id="cityDiv">
   </div>
 </div>
 <div id="mainArea">
  <p class="goText">Wiem co lubisz? Co powiesz na:</p>
  <hr />
  
  <div id="userLikes">
  </div>
 </div>
</div>

1.3 Wprowadzenie przykładowych danych.
Na razie nie mamy żadnego połączenia z Facebookiem, więc na potrzeby stylizacji wprowadzimy przykładowe dane. Kod może wyglądać tak:

<div id="frame">
 <div id="topPanel">
   <div id="photoDiv">
    <img id="userPhoto" src="http://graph.facebook.com/100000027824838/picture?type=normal" />
   </div>
   
   <div id="nameDiv">
    <p>Norbert</p>
    <p>Kozlowski</p>
   </div>
   
   <div id="cityDiv">
    <p>Aktualne miasto:</p>
    <p class="cityName">Wroclaw</p>
   </div>
 </div>
 <div id="mainArea">
  <p class="goText">Wiem co lubisz? Co powiesz na:</p>
  <hr />
  
  <div id="userLikes">
   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
 Nulla at turpis eget nibh ultricies dignissim. Duis luctus
 euismod turpis. Mauris augue. Aliquam facilisis semper elit.
 Pellentesque semper hendrerit arcu. Phasellus eleifend
 commodo justo. Aliquam orci urna, imperdiet sit amet,
 posuere in, lobortis et, risus. Integer interdum nonummy
 erat. Nullam tellus. Sed accumsan. Vestibulum orci ipsum,
 eleifend vitae, mollis vel, mollis sed, purus. Suspendisse
 mollis elit eu magna. Morbi egestas. Nunc leo ipsum, blandit
 ac, viverra quis, porttitor quis, dui. Vestibulum ante ipsum
 primis in faucibus orci luctus et ultrices posuere cubilia
 Curae; Vivamus scelerisque ipsum ut justo. Pellentesque et
 ligula eu massa sagittis rutrum. In urna nibh, eleifend vel,
 suscipit ut, sagittis id, nunc.
  </div>
 </div>
</div>

W kodzie użyto zdjęcia pobranego z Facebooka. Nazwę miasta wprowadzono w klasie .cityName by ułatwić proces stylizacji który odbędzie się w następnym kroku. Sekcję #userLikes wypełniłem przykładowym tekstem. Niżej aktualny podgląd strony w przeglądarce.

1.4 Dołączenie styli
W zasadzie moglibyśmy pominąć ten krok, bo nie jest on konieczny do osiągnięcia celu. Miło jest popatrzeć na coś ładnie się prezentującego, dlatego poświęcimy trochę czasu wklepując kod. Wykorzystałem tu dwa elementy standardu CSS3 - cienie napisów oraz formatowanie tekstu w kolumnach. Internet Explorer nie obsługuje poprawnie tych możliwości.

p {
  padding:0;
  margin:0;
 }
 
 #frame {
  width:750px;
 }
 
 #topPanel {
  height:140px;
  background-color: #4aa0e8;
  padding-left:10px;
  padding-right:5px;
  border:1px solid #3e33ff;
 }
 
 #photoDiv {
  float:left;
  width:102px;
  padding-top:10px;
 }
 
 #nameDiv p {
  font-family: "Blackadder ITC";
  font-size:47px;
  
  text-shadow: 3px 3px 2px #808080;
  -moz-text-shadow: 3px 3px 2px #808080;
  -webkit-text-shadow: 3px 3px 2px #808080;
 }
 
 #nameDiv {
  float: left;
  padding-top:10px;
  padding-left:5px;
 }
 
 #cityDiv {
  float:right;
  text-align:right;
  line-height: 15px;
  margin-top:10px;
  margin-right:10px;
  font-family:"Calisto MT";
 }
 
 #cityDiv .cityName {
  text-transform: uppercase;
  font-weight:bold;
  margin-top:5px;
 }
 
 #userPhoto {
  border:1px solid white;
  height:80%;
 }
 
 #mainArea {
  margin-top:3px;
  background-color:#ff8040;
  border:1px solid #804000;
  padding:0 5px 5px 5px;
  text-align:justify;
 }
 
 #userLikes {
  font-family:Tahoma;
  font-size:12px;
  line-height:18px;
  
  -moz-column-count: 3;
  -moz-column-gap: 20px;
  
  -webkit-column-count: 3;
  -webkit-column-gap: 20px;
 }
 
 #mainArea .goText {
  margin-top:3px;
  margin-bottom:3px;
  width:100%;
  font-family:Tahoma;
  text-align:center;
 }

Opakujmy ten styl pomiędzy znacznik <style> i umieśćmy przed głównym kodem HTML. Jak prezentuje się strona w różnych przeglądarkach?

Firefox 5.0

Safari 5.0.5

Internet Explorer 9.0 64bit

Internet Explorer nie obsługuje cienia rzucanego przez imię i nazwisko, nie dzieli tekstu na trzy kolumny, oraz ma problemy z interpretacją źródła do obrazka. Trzeba to uwzględnić przy projektowaniu większych aplikacji. Nie jest naszym celem stworzenie teraz aplikacji, która będzie poprawnie obsługiwana przez wszystkie przeglądarki, ale pobieranie danych poprzez Facebook Graph API i na tym się skupimy.

Mając gotową stronę, możemy przejść do drugiego kroku, czyli do tworzenia ...

2. Skrypt PHP

1.1  Skrypt autoryzujący pobierający dodatkowe informacje

Korzystając z informacji w tym wpisie zalążkiem naszego skryptu będzie właśnie to co napisaliśmy. Zacznijmy od następującego kodu stopniowo go modyfikując.
<?php
 // Nr ID aplikacji
 $app_id = '179524192103712';
 // Adres canvas aplikacji
 $canvas_page = 'http://apps.facebook.com/khozzyaps/';
 // Tworzenie adresu url zgodnego ze standardem OAuth
 // Pobieramy dodatkowo takie informacje jak lubiane rzeczy oraz lokalizacje uzytkownika
 $auth_url = 'http://facebook.com/dialog/oauth?client_id=' . $app_id . '&redirect_uri=' . urlencode($canvas_page) 
 . '&scope=user_likes,user_location';
 // Odebranie danych i zapisanie jej do zmiennej
 $signed_request = $_REQUEST["signed_request"];
 // Dzielimy odebrane dane wzgledem kropki na dwie czesci
 list($encoded_sig,$payload) = explode('.',$signed_request,2);
 // Dekodujemy druga czecs odebranych danych i zapisujemy je do zmiennej
 $data = json_decode(base64_decode(strtr($payload,'_-',' /')), true);
 
 // Jezeli nie zautoryzowano uzytkownika, przenies go z powrotem na strone autoryzacji
 if (empty($data["user_id"])) {
  echo("<script> top.location.href='" . $auth_url . "'</script>");
 }
 // Jezli wszystko odbylo sie poprawnie mozemy kontynuowac
 else {
  
  // TU WLASCIWY KOD
 }
?>
Jak już wiadomo, odbywa się tu procedura autoryzacji użytkownika, w której prosimy także o udostępnienie informacji o jego lokalizacji i lubianych rzeczach. Jeśli uzyskano zgodę (tym samym zwrócony został obiekt signed_request zawierający wymagany access_token) możemy przejść do właściwego fragmentu kodu.

1.2 Tworzenie zapytań

Mając obiekt signed_request zapisany w zmiennej $data, wyłuskajmy z niego i zapiszmy ID użytkownika oraz wygenerowany klucz.
$user_id = $data['user_id'];
$access_token = $data['oauth_token'];
Ułatwi to nam konstruowanie zapytań do serwera Graph.

Aby pobrać informacje o imieniu, nazwisku i miejscu zamieszkania a następnie zapisać je, musimy stworzyć zapytanie w odpowiednim formacie. Wszystko opisałem w tym wpisie.
$graph_url = "https://graph.facebook.com/" . $user_id .
"?access_token=" . $access_token;
$response = file_get_contents($graph_url);
$user_info_response = json_decode($response,true);
Na początku tworzone jest ogólne zapytanie w którym argumentami są ID użytkownika i access_token zwrócony przez niego (abyśmy mogli dostać się do prywatnych zasobów). $graph_url jest adresem przechowującym obiekt tekstowy JSON. Pobierzmy te dane i zapiszmy do kolejnej zmiennej. Możemy użyć funkcji curl() (która w tym przypadku jest odrobinę zbyt skomplikowana) lub file_get_contents(). Używając tej drugiej kopiujemy zawartość pliku wskazanego przez $graph_url do zmiennej $response. Nadal jest to tekstowy obiekt JSON. Aby dekodować dane wykonujemy funkcję json_decode(). Drugi parametr true() powoduje, że  $user_info_response jest tablicą asocjacyjną (przechowującą informacje w formacie nazwa-wartość) przechowującą informacje o użytkowniku. Nie podanie tego parametru spowodowałoby utworzenie obiektu stdClass, a co za tym idzie  inny sposób odwoływania się do jej składowych.

Pobierzmy w ten sposób informacje o rzeczach lubianych przez użytkownika.
$likes_url = "https://graph.facebook.com/" . $user_id . 
"/likes?access_token=" . $access_token;
$likesResponse = file_get_contents($likes_url);
$likes_info_response = json_decode($likesResponse);
Dodajmy kod diagnostyczny, aby sprawdzić czy wszystko wygląda na pewno tak jak oczekujemy.
echo '<pre>';
print_r($user_info_response);
print_r($likes_info_response);
echo '</pre>';
Wynik działania przedstawiono na zrzucie ekranu.

Tak jak zakładaliśmy, zaznaczony fragment jest tablicą asocjacyjną przechowującą ogólne informacje o użytkowniku, a kod niżej jest klasą stdClass zawierającą tablicę data z jego ulubionymi rzeczami.

1.3 Wyłuskanie danych

Aby pobrać i zapisać imię, nazwisko i miasto, które są zapisane w tablicy wpisujemy po prostu:
$userName = $user_info_response['first_name'];
$userLastName = $user_info_response['last_name'];
$userCity = $user_info_response['location']['name'];
Jeśli dane te byłyby zapisane jako obiekt, odwołuje się do nich w analogiczny sposób:
$userName = $user_info_response->first_name;
$userLastName = $user_info_response->last_name;
$userCity = $user_info_response->location->name;
Tablica, zawierająca lubiane przedmioty:
$likesArray = $likes_info_response->data;
Którą możemy także wylistować:
for ($i = 0; $i < sizeof($likesArray); $i++) {
 echo $likesArray[$i]->name;
}
Pozostaje nam zapisanie adresu zdjęcia profilowego użytkownika:
$userPhotoAddress = "http://graph.facebook.com/ " . 
$user_id . "/picture?type=normal";

3. HTML + PHP

3.1 Dodanie szablonu strony do kodu PHP

Wykorzystując funkcję echo() wkleimy do skryptu PHP cały kod HTML który napisaliśmy w punkcie pierwszym.
else {
  $access_token = $data['oauth_token'];
  $user_id = $data['user_id'];
  
  // Pobranie info o uzytkowniku
  $graph_url = "https://graph.facebook.com/" . $user_id .
 "?access_token=" . $access_token;
  $response = file_get_contents($graph_url);
    $user_info_response = json_decode($response,true);
  
  // Pobranie info o lubionych przedmiotach
  $likes_url = "https://graph.facebook.com/" . $user_id . 
"/likes?access_token=" . $access_token;
  $likesResponse = file_get_contents($likes_url);
  $likes_info_response = json_decode($likesResponse);
  
  $userName = $user_info_response['first_name'];
  $userLastName = $user_info_response['last_name'];
  $userCity = $user_info_response['location']['name'];
  
  // Tablica z lubianymi przedmiotami
  $likesArray = $likes_info_response->data;
  
  // Adres ze zdjeciem profilowym
  $userPhotoAddress = "http://graph.facebook.com/ " 
. $user_id . "/picture?type=normal";
  
  echo '
   TU KOD HTML WITYRYNY
  ';

  //for ($i = 0; $i < sizeof($likesArray); $i  ) {
  // echo '<b>=> </b>' . $likesArray[$i]->name;
  //}
 }
Gdzie napisany przez nas kod witryny to:

<style>
 p {
  padding:0;
  margin:0;
 }
 
 #frame {
  width:750px;
 }
 
 #topPanel {
  height:140px;
  background-color: #4aa0e8;
  padding-left:10px;
  padding-right:5px;
  border:1px solid #3e33ff;
 }
 
 #photoDiv {
  float:left;
  width:102px;
  padding-top:10px;
 }
 
 #nameDiv p {
  font-family: "Blackadder ITC";
  font-size:47px;
  
  text-shadow: 3px 3px 2px #808080;
  -moz-text-shadow: 3px 3px 2px #808080;
  -webkit-text-shadow: 3px 3px 2px #808080;
 }
 
 #nameDiv {
  float: left;
  padding-top:10px;
  padding-left:5px;
 }
 
 #cityDiv {
  float:right;
  text-align:right;
  line-height: 15px;
  margin-top:10px;
  margin-right:10px;
  font-family:"Calisto MT";
 }
 
 #cityDiv .cityName {
  text-transform: uppercase;
  font-weight:bold;
  margin-top:5px;
 }
 
 #userPhoto {
  border:1px solid white;
  height:80%;
 }
 
 #mainArea {
  margin-top:3px;
  background-color:#ff8040;
  border:1px solid #804000;
  padding:0 5px 5px 5px;
  text-align:justify;
 }
 
 #userLikes {
  font-family:Tahoma;
  font-size:12px;
  line-height:18px;
  
  -moz-column-count: 3;
  -moz-column-gap: 20px;
  
  -webkit-column-count: 3;
  -webkit-column-gap: 20px;
 }
 
 #mainArea .goText {
  margin-top:3px;
  margin-bottom:3px;
  width:100%;
  font-family:Tahoma;
  text-align:center;
 }
</style>
<div id="frame">
 <div id="topPanel">
   <div id="photoDiv">
    <img id="userPhoto" src="http://graph.facebook.com/100000027824838/picture?type=normal" />
   </div>
   
   <div id="nameDiv">
    <p>Norbert</p>
    <p>Kozlowski</p>
   </div>
   
   <div id="cityDiv">
    <p>Aktualne miasto:</p>
    <p class="cityName">Wroclaw</p>
   </div>
 </div>
 <div id="mainArea">
  <p class="goText">Wiem co lubisz? Co powiesz na:</p>
  <hr />
  
  <div id="userLikes">
   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
 Nulla at turpis eget nibh ultricies dignissim. Duis luctus
 euismod turpis. Mauris augue. Aliquam facilisis semper elit.
 Pellentesque semper hendrerit arcu. Phasellus eleifend
 commodo justo. Aliquam orci urna, imperdiet sit amet,
 posuere in, lobortis et, risus. Integer interdum nonummy
 erat. Nullam tellus. Sed accumsan. Vestibulum orci ipsum,
 eleifend vitae, mollis vel, mollis sed, purus. Suspendisse
 mollis elit eu magna. Morbi egestas. Nunc leo ipsum, blandit
 ac, viverra quis, porttitor quis, dui. Vestibulum ante ipsum
 primis in faucibus orci luctus et ultrices posuere cubilia
 Curae; Vivamus scelerisque ipsum ut justo. Pellentesque et
 ligula eu massa sagittis rutrum. In urna nibh, eleifend vel,
 suscipit ut, sagittis id, nunc.
  </div>
 </div>
</div>
Należy zamienić takie miejsca jak:
  • #photoDiv
  • #nameDiv
  • #cityDiv
  • #userLikes
Aby poszczególne sekcje pobierały dane ze zmiennych, należy podmienić wpisane przykładowe wartości nazwami zmiennych. Więc:
<div id="photoDiv">
 <img id="userPhoto" src="' . $userPhotoAddress . '" />
</div>
Zamiana imienia i nazwiska:
<div id="nameDiv">
 <p>' . $userName . '</p>
 <p>' . $userLastName . '</p>
</div>
miasta:
<div id="cityDiv">
 <p>Aktualne miasto:</p>
 <p class="cityName">' . $userCity . '</p>
</div>
Wypisanie lubianych przedmiotów
<div id="userLikes">';

 for ($i = 0; $i < sizeof($likesArray); $i  ) {
  echo '<b>=> </b>' . $likesArray[$i]->name;
 }
  
echo ' 
</div>
Użyłem apostrofów, aby wyjść funkcji echo, wypisać całą zawartość tablicy, a potem znowu ją wywołać, aby pozamykać pozostałe sekcje. Warto też dodać znacznik nowej linii po każdym przedmiocie (tutaj był pomijany). Całość widać na zrzucie ekranu

Wnioski
Przykładowe screeny:

Napotkane problemy wymagające rozwiązania: kompatybilność z przeglądarkami (poprawne wyświetlanie zdjęcia), kodowanie polskich znaków.
Założony cel osiągnięty.

sobota, 18 czerwca 2011

Jak przebiega autoryzacja aplikacji na Facebooku? Krok po kroku.

Aby uzyskać autoryzację dla aplikacji Facebookowej developerzy zalecają korzystanie z protokołu OAuth 2.0 Dialog (jest to standard pozwalający dzielić się swoimi prywatnymi materiałami z innymi). Do wykorzystania są także popularne biblioteki JS SDK lub PHP SDK ułatwiające pracę. Tu jednak poruszone zostanie klasyczne rozwiązanie.

Autoryzację OAuth w Facebooku wykonujemy przekierowując użytkownika na adres URL, stworzony według schematu: 
  
https://www.facebook.com/dialog/oauth?
client_id=YOUR_APP_ID
&redirect_uri=YOUR_CANVAS_PAGE


Gdzie YOUR_APP_ID jest identyfikatorem aplikacji , a YOUR_CANVAS_PAGE ścieżką URL do naszego  serwera który ją przechowuje. Domyślnie adres ten uzyskuje dostęp do podstawowych informacji o użytkowniku. Aby pobrać więcej danych, musimy wymienić żądane informacje, po parametrze scope. Poniższy przykład pokazuje jak uzyskać dostęp do adresu e-mail oraz pola news feed (czyli informacji o aktywności znajomych) 

https://www.facebook.com/dialog/oauth?
client_id=YOUR_APP_ID  
&redirect_uri=YOUR_CANVAS_PAGE 
&scope=email,user_status,user_location 

Pełna lista informacji jakie możemy pobrać dostępna jest na tej stronie. Istnieje pewna zależność pomiędzy ilością zbieranych danych, a liczbą użytkowników zezwalających na ich udostępnianie. Mianowicie, im więcej danych żądamy, mniej użytkowników będzie korzystało z naszej aplikacji.

W przypadku gdy użytkownik odmówi udostępnienia informacji, przeglądarka przekieruje go na adres wygenerowany na podstawie podanego wcześniej redirect_uri, zwracając błędy:

http://YOUR_CANVAS_PAGE?
error_reason=user_denied
&error=access_denied
&error_description=The+user+denied+your+request.

 
W przypadku, gdy użytkownik zezwala na udostępnianie informacji o które został poproszony, aplikacja przekierowuje go na adres podany w redirect_uri ustawiając parametr signed_request. Parametr ten jest połączeniem funkcji hashującej HMAC SHA-256, znaku ‘.’ oraz obiektu JSON zakodowanego algorytmem base64url. Może wyglądać np. tak (bez znaków nowej linii)
vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso.
eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0 
Sygnatura HMAC zapewnia, że przesyłane dane pochodzą z serwisu Facebook (dzięki kodowaniu przez tajny kod App Secret znany tylko twórcy aplikacji).

Dalej zakodowany jest obiekt JSON. Jest to format tekstowy używany przy wymianie danych przez skrypty. Często używa się go przy okazji wykorzystania technologii AJAX. Obsługa odebranego ciągu znaków ogranicza się do zastosowania na nim funkcji eval() (JS). Zamienia ona dane JSON na dane w formacie tablicy. Dostęp do nich uzyskujemy poprzez nazwę i indeksy pól. Na przykład odebranaDana.tytul lub odebranaDana.tresc.

W przypadku języka PHP, wystarczy na tablicy danych zastosować funkcję json_encode(), aby zamienić je na format JSON. Dekodowanie wykonujemy analogicznie wykorzystując funkcję json_decode().

Obiekt signed_request zawiera następujące pola:

·         user
Tablica JSON zawierająca takie informacje jak kraj z którego pochodzi użytkownik, zakres wieku w jakim się plasuje, locale (czyli ustawienia zmiennych środowiskowych).
·         algorithm
Ciąg znaków JSON zawierający nazwę algorytmu użytego do zakodowania żądania.
·         issued_at
Liczba JSON w formacie POSIX, informująca kiedy żądanie zostało zrealizowane.
·         user_id
Ciąg znaków JSON zawierający identyfikator bieżącego użytkownika (UID).
·         oauth_token
Ciąg znaków JSON wykorzystywany przy korzystaniu z Graph API.
·         expires
Liczba JSON zawierająca czas w formacie POSIX, którego data wyznacza okres wygaśnięcia oauth_token.

Poniższy kod PHP demonstruje zasadę działania procesu autoryzacji oraz wyświetla zawartość zmiennej signed_request w formacie przyjaznym użytkownikowi.
<?php
 # Nr ID aplikacji
 $app_id = '179524192103712';
 # Adres canvas aplikacji
 $canvas_page = 'http://apps.facebook.com/khozzyaps/';
 # Tworzenie adresu url zgodnego ze standardem OAuth
 # Pobieramy dodatkowo takie informacje jak email, status oraz lokalizacje uzytkownika
 $auth_url = 'http://facebook.com/dialog/oauth?client_id=' . $app_id . '&redirect_uri=' . urlencode($canvas_page) 
 . '&scope=email,user_status,user_location';
 # Odebranie danych i zapisanie jej do zmiennej
 $signed_request = $_REQUEST["signed_request"];
 # Dzielimy odebrane dane wzgledem kropki na dwie czesci
 list($encoded_sig,$payload) = explode('.',$signed_request,2);
 # Dekodujemy druga czecs odebranych danych i zapisujemy je do zmiennej
 $data = json_decode(base64_decode(strtr($payload,'_-',' /')), true);
 
 # Jezeli nie zautoryzowano uzytkownika, przenies go z powrotem na strone autoryzacji
 if (empty($data["user_id"])) {
  echo("<script> top.location.href='" . $auth_url . "'</script>");
 }
 # Jezli wszystko odbylo sie poprawnie wyswietl zawartosc zmiennej $data w formie przyjaznej uzytkownikowi
 else {
  echo "<pre>";
  echo print_r($data); 
  echo "</pre>";
 }
 
?>

Oraz zrzut ekranu prezentujący działanie aplikacji: