MySQL / PHP Facebook Auto Login/Register

05/16/2012 10:08 boxxiebabee#1
Servus,

da ich schon recht lange Zeit nichts mehr mit PHP gemacht habe und hier viel zu wenig Release, hab ich mich mal an nem Facebook Auto-Login/Register versucht.

Zuerst eine kurze Erklärung zu den Dateien im Anhang:

base_login.php
PHP Code:
<?php
require(dirname(__FILE__).'/ez_sql_core.php');
require(
dirname(__FILE__).'/ez_sql_mysql.php');
class 
Base_Login
{
    protected 
$member_uri 'member.php';
    protected 
$home_uri 'index.php';
    protected 
$db;
    protected 
$Session;
    
    private 
$avatar_path =  dirname(dirname(__FILE__)).'/images/avatar/'//Pfad zum Ordner wo die Avatare gespeichert werden.
    
private $days_update 7//Nach wievielen Tagen sollen die Info's vom User upgedatet werden?
    
    
    
public function __construct($db_user$db_password$db_name$db_host)
    {   
        
//Überprüft ob der User bereits eingeloggt ist.
        
if (!isset($_SESSION['user'])) {
            
$this->db = new ezSQL_mysql($db_user$db_password$db_name$db_host);
        } else {
            
//Wenn ja, dann leite Ihn auf die Member Seite weiter.
            
$this->Redirect($this->member_uri);
        }
    }
    
    
//Berechne die differenz von zwei Datetime / Timestamp Daten. Gibt den Unterschied in Tagen zurück.
    
private function dateDiff($time1$time2)
    {
        if (!
is_int($time1)) {
            
$time1 strtotime($time1);
        }
        if (!
is_int($time2)) {
            
$time2 strtotime($time2);
        }
        if (
$time1 $time2) {
            
$temp  $time1;
            
$time1 $time2;
            
$time2 $temp;
        }
        
$diff $time2 $time1;
        return 
floor($diff / (60 60 24));
    }
    
    
//Echte IP vom User bekommen. (Nur bei relativ schlecht eingestellten Proxy's)
    
private function getIP()
    {
        if (isset(
$_SERVER['HTTP_CLIENT_IP'])) {
            return 
$_SERVER['HTTP_CLIENT_IP'];
        } elseif (isset(
$_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return 
$_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset(
$_SERVER['HTTP_X_FORWARDED'])) {
            return 
$_SERVER['HTTP_X_FORWARDED'];
        } elseif (isset(
$_SERVER['HTTP_FORWARDED_FOR'])) {
            return 
$_SERVER['HTTP_FORWARDED_FOR'];
        } elseif (isset(
$_SERVER['HTTP_FORWARDED'])) {
            return 
$_SERVER['HTTP_FORWARDED'];
        } else {
            return 
$_SERVER['REMOTE_ADDR'];
        }
    }
    
    
//Variablen 'entschärfen'.
        //Info: Warum werden die Variablen die von Facebook kommen gegen SQLi geschützt?
       //Der Name vom User könnte eine SQLi Attacke beinhalten -> Habs getestet und funktioniert wenn man es
      // nicht schützt!
    
private function escapeVariables()
    {
        
$args func_get_args();
        
$var = array();
        for(
$i 0$total=count($args); $i $total$i++)
        {
            if(
is_int($args[$i]))
            {
                
$var[$i] = intval($args[$i]);
            }
            else if(
is_string($args[$i]))
            {
                
$var[$i] = mysql_real_escape_string($args[$i]);
            }
        }
        return 
$var;
    }
    
    
//Zu einer bestimmten Seite weiterleiten.
    
protected function Redirect($url)
    {
        
header('Location: ' $url);
    }
    
    
//Avatar vom einer Url downloaden und speichern.
    
protected function saveAvatar($url$id)
    {
        
$file $this->avatar_path $id '.jpg';
        
$ch   curl_init($url);
        
curl_setopt($chCURLOPT_HEADER0);
        
curl_setopt($chCURLOPT_RETURNTRANSFER1);
        
curl_setopt($chCURLOPT_BINARYTRANSFER1);
        
$raw curl_exec($ch);
        
curl_close($ch);
        if (
file_exists($file)) {
            
unlink($file);
        }
        
$fp fopen($file'x');
        
fwrite($fp$raw);
        
fclose($fp);
    }
    
    
//Setzt die Session damit der User eingeloggt ist.
    
protected function setSession($id$uid$pid$first_name$last_name)
    {
        
//TODO: Secure Session Management to prevent session hijacking.
        
$_SESSION['user']['id']             = $id;
        
$_SESSION['user']['oauth_uid']      = $uid;
        
$_SESSION['user']['oauth_provider'] = $pid;
        
$_SESSION['user']['first_name']     = $first_name;
        
$_SESSION['user']['last_name']      = $last_name;
    }
    
    
//Checkt ob der User bereits Registriert ist.
    
protected function IsRegistered($uid$pid)
    {
        
$var $this->escapeVariables($uid$pid);
        return 
$this->db->get_row("SELECT * FROM users WHERE oauth_provider_id={$var[1]} AND oauth_uid='{$var[0]}'");
    }
    
    
//Registriert einen User.
    
protected function Register($pid$uid$first_name$last_name$email$gender)
    {
        
$var $this->escapeVariables($pid$uid$first_name$last_name$email$gender);
        
$this->db->query("INSERT INTO users (oauth_provider_id,oauth_uid,first_name,last_name,email,gender,ip,isAdmin, last_update)
                          VALUES (
{$var[0]},'{$var[1]}','{$var[2]}','{$var[3]}','{$var[4]}','{$var[5]}','{$this->getIP()}',0, Now())");
        return 
$this->db->get_row("SELECT * FROM users WHERE ID={$this->db->insert_id}");
    }
    
    
//Gibt die Provider ID zurück.
    
protected function getProviderID($name)
    {
        
$var $this->escapeVariables($name);
        return 
$this->db->get_var("SELECT id FROM oauth_providers WHERE provider_name='{$var[0]}'");
    }
    
    
//Updated den User.
    
protected function Update($pid$uid$first_name$last_name$email$gender)
    {
        
$var $this->escapeVariables($id$first_name$last_name$email$gender);
        
$this->db->query("UPDATE users SET first_name='{$var[1]}', last_name='{$var[2]}', email='{$var[3]}',gender='{$var[4]}',last_update=Now() WHERE ID={$var[0]}");
    }
    
    
//Checkt ob der User upgedatet werden soll.
    
protected function needUpdate($id)
    {
        
$datetime $this->db->get_var("SELECT last_update FROM users WHERE ID={$id}");
        
$days     $this->dateDiff($datetimetime());
        if (
$days >= $this->days_update){
            return 
true;
        }
        else{
            return 
false;
        }
    }
}
?>

facebook_login.php
PHP Code:
<?php
require(dirname(__FILE__).'/facebook.php');
class 
Facebook_Login extends Base_Login
{
    private 
$facebook;
    private 
$provider_id;

    public function 
__construct($db_user$db_password$db_name$db_host$app_id$secret)
    {
            
parent::__construct($db_user$db_password$db_name$db_host);
            
$this->facebook    = new Facebook(array(
                
'appId'  => $app_id,
                
'secret' => $secret,
                
'cookie' => true
            
));
            
$this->provider_id $this->getProviderID('facebook');
    }
    
    public function 
Login()
    {
        
$session $this->facebook->getUser();
        
//Ist der User in Facebook eingeloggt?
        
if (!empty($session)) {
            try {
                
//Wenn ja, entweder um berechtigungen Fragen oder Infos holen.
                
$user $this->facebook->api('/me');
            }
            catch (
FacebookApiException $e) {
                echo 
$e;
                
$user null;
            }
            if (!empty(
$user)) {
                
//Ist der User bereits registriert?
                
$result $this->IsRegistered($user['id'], $this->provider_id);
                if (empty(
$result)) {
                    
//Wenn nicht, dann registriere Ihn und speichere seinen Avatar.
                    
$result $this->Register($this->provider_id$user['id'], $user['first_name'], $user['last_name'], $user['email'], $user['gender']);
                    
$this->saveAvatar($this->getAvatarUrl($user['id']), $this->provider_id$user['id']);
                } else {
                    
//Sollen die Infos / Avatar vom User upgedatet werden?
                    
if ($this->needUpdate($result->ID)) {
                        
//Wenn ja, update und speichere seinen Avatar.
                        
$this->Update($result->ID$user['first_name'], $user['last_name'], $user['email'], $user['gender']);
                        
$this->saveAvatar($this->getAvatarUrl($user['id']), $result->ID);
                    }
                }
                
//Setze eine Session und leite ihm zur Member Page weiter.
                
$this->setSession($result->ID$result->oauth_uid$result->oauth_provider_id$result->first_name$result->last_name);
                
$this->Redirect($this->member_uri);
            } else {
                die(
'There was an error.');
            }
        } else {
            
//Schickt den User zum Facebook-Login.
            
$this->Redirect($this->LoginUrl());
        }
    }
    
    
//Von Facebook die LoginUrl bekommen.
    
private function LoginUrl()
    {
        return 
$this->facebook->getLoginUrl(array('scope' => 'email'));
    }
    
    
//Echten Link zum Facebook Avatar bekommen.
    
private function getAvatarUrl($uid)
    {
        
$headers get_headers('http://graph.facebook.com/' $uid '/picture?type=large'1);
        if (isset(
$headers['Location'])) {
            return 
$url $headers['Location'];
        }
        else{
            return 
false;
        }
    }
}
?>
So. Aber wie geht man nun vor?
1. Eine neue Datenbank anlegen und die SQL-Datei importieren.
2. [Only registered and activated users can see links. Click Here To Register...] aufrufen und eine neue App erstellen. Display Name, App Domains und bei 'Website with Facebook Login' Adresse der Webseite ausfüllen.
3. AppID & Secret von der App kopieren.
4. In der config.php Datei die benötigten Felder ausfüllen.
5. Auf nen Server hochladen, oder local über xampp. (Achtung, die Domain was auf Facebook angegeben wurde, muss mit der übereinstimmen wo die Seite läuft)
5.1. Um es auf dem localhost zu überprüfen, müsst ihr in xampp einen neuen vhost anlegen, z.B. localhost.com(diese 'Domain' muss dann auch bei Facebook eingetragen werden). Und in der Windows-Host Datei muss ein Eintrag gesetzt werden: '127.0.0.1 localhost.com'
6. Fertig ;)