Android&PHP Backend: Netzwerkkommunikation, Authentifizierung und Login

Aufgabenstellung

Es wird eine Möglichkeit gesucht eine Android App mit einen PHP Backend kommunizieren zu lassen

Intention

PHP mit MySQL Server erhält man oft schon mit billigem Webspace. Ein weiterer Vorteil eines fertigen Webpacks/Webspace ist, dass es nicht notwendig wird sich um eine Backupstrategie zu kümmern. In den meisten Fällen (SLAs und AGBs des Providers studieren) liegt dieses Problem in den Händen des Providers. Er kümmert sich auch um die Sicherheit des Servers. Bei Hackerattacken ist man nicht in der Verantwortung den Server zu härten und zu schützen. Daher kann der Provider auch keine Schadensersatzansprüche gegen den Kunden geltend machen, wenn ein Server gekapert wird und z.B. mit der Installation eines Botnetzes die Leistungsfähigkeit des Rechenzentrums beeinträchtigt ist.

Ansatz

  • Implementierung eines möglichst einfachen Authentifierungsmechanismus in PHP mit MySQL-Anbindung
  • Wegkapseln der Serviceaufrufe
  • Asynchrone Verarbeitung der JSON Aufrufe per Java Thread
    • Reaktion in der MainActivity beim Erhalten des Service-Ergebnisses für UI Manipulationen

Der häufigste Ansatz, den man in Tutorials findet, ist die Kommunikation über JSON, einem kompakten Datenformat in für Mensch und Maschine einfach lesbarer Textform zum Zweck des Datenaustauschs zwischen Anwendungen.

Lösung

BjoernServiceCaller.java – Klasse für weggekapselte Service aufrufe mit CallBack-Funktionalität über onLoginResult

package com.caprisoft.contactupload.services;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import com.caprisoft.contactupload.MainActivity;

import android.content.Context;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;


public class BjoernsServiceCaller 
{
	
	final String authenticationURL = "authenticationservice.php";
	private static BjoernsServiceCaller instance = null;
	private BjoernsServiceCaller() 	{}
	

    /**
     * Statische Methode, liefert die einzige Instanz dieser
     * Klasse zurück
     */
    public static BjoernsServiceCaller getInstance() 
    {
        if (instance == null) 
        {
            instance = new BjoernsServiceCaller();
        }
        return instance;
    }
	
	
	public void loginUser(final MainActivity ctx, 
                                    final String email, final String password) 
	{
        Thread t = new Thread()
        {
	        public void run() 
	        {
                        //For Preparing Message Pool for the child Thread
		        Looper.prepare(); 
				
		        HttpClient client = new DefaultHttpClient();
                         //Timeout Limit
		        HttpConnectionParams
                               .setConnectionTimeout(client.getParams(), 10000);
		        HttpResponse response;
		        JSONObject json = new JSONObject();
		        try
		        {
		            HttpPost post = new HttpPost(authenticationURL);
		            json.put("email", email);
		            json.put("password", password);
		            StringEntity se = new StringEntity( json.toString());  
		            se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
                                          application/json"));
		            post.setEntity(se);
		            response = client.execute(post);
		            /*Checking response */
		            if(response!=null)
		            {
		                BufferedReader reader = new BufferedReader
                                (
                                    new InputStreamReader
                                    (
                                       response.getEntity().getContent(), "UTF-8"
                                    )
                                );
		                String derText = reader.readLine();
                                // CallBack aufruf in MainActivity
		                ctx.onLoginResult(derText);
		            }
		
		        }
		        catch(Exception e)
		        {
		            e.printStackTrace();
		        }
		        Looper.loop(); //Loop in the message queue
	        }
        };
        t.start();          
    }
}

authenticationservice.php – Das PHP Backend, was die Datenbankabfragen macht und auf jedem Billigwebspace läuft

<?php  
    include("configuration/database.php");
	$json = file_get_contents('php://input');
	$obj = json_decode($json);
	$result2=mysql_query("SELECT id, activationcode FROM users ".
                                      "WHERE email='".$obj->{'email'}."' AND ".
                                      "password='".$obj->{'password'}."'") 
                                       or die(mysql_error());
	
	$user="nouser";
	while ($row = mysql_fetch_array($result2, MYSQL_NUM)) {
	   $user=$row[0];
	   $activationcode=$row[1];
	}	
    
    $posts = array(1);
    
    if($user!="nouser")
    {
    	if($activationcode=="activated")
    	{
    		session_start();
    		session_register("userid");
    		$_SESSION["userid"] =$user;
    		header('Content-type: application/json');
    		echo "success";
    	}
    	else 
    	{
    	   $registrationcode=substr(md5($obj->{'email'}." ".$obj->{'password'}),6);
    	   mysql_query("UPDATE users SET activationcode='".$registrationcode.
           "' WHERE email='".$obj->{'email'}."'") or die(mysql_error());
    	   mail($obj->{'email'},"Registrationcode for contactupload.com",
            "Hello!<br><br>\n You or someone else has registered this email ".
            "address via mobile phone.<br><br>\nThe generated registrationcode is ".
            $registrationcode.".<br><br>\nPlease type this registrationcode in ".
            "the register section of the contact sync app.<br><br> .
            "\nWith best regards,<br>\ncontactupload.com");
    		echo "not activated";
    	}
    }
    else 
    {
        echo "not registered";
    } 
    mysql_close($con);
?>

MainActivity.java – Die Klasse präsentiert den Code der Benutzeroberfläche der Activity (VIEW)

package com.caprisoft.contactupload;

import com.caprisoft.contactupload.services.BjoernsServiceCaller;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
	
	private EditText email = null;
	private EditText passwort = null;
	
	/** Called when the user selects the Send button */
	public void onClickLoginButton(View view) {
	    // Do something in response to button
		Log.d(this.getClass().toString(), "Login Button gedrückt!");
		BjoernsServiceCaller.
                getInstance().
                loginUser
                (
                    this, 
                    email.getText().toString(), 
                    passwort.getText().toString()
                );
	}
	
	/** Called when the user selects the Send button */
	public void onClickRegisterButton(View view) {
	    // Do something in response to button
		Log.d(this.getClass().toString(), "Register Button gedrückt!");
	}	
	
	public void onLoginResult(String text)
	{
		Toast.makeText(this, "HALLO: "+text, Toast.LENGTH_LONG).show();
	}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        email = (EditText) findViewById(R.id.textUsername);
        passwort = (EditText) findViewById(R.id.textPassword);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    
}

Activity_main.xml – Das eigentliche Frontend

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/labelUsername"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/labelUsername"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
  <EditText android:id="@+id/textUsername"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:inputType="textNoSuggestions"
        android:hint="@string/hintUsername" />
  
   <TextView
        android:id="@+id/labelPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/labelPassword"
        android:textAppearance="?android:attr/textAppearanceLarge" />
      
   <EditText android:id="@+id/textPassword"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:inputType="textPassword"
        android:hint="@string/hintPassword" />

   <Button
       android:id="@+id/buttonLogin"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="onClickLoginButton"
       android:text="@string/buttonLogin" />

   <Button
       android:id="@+id/buttonRegister"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:onClick="onClickRegisterButton"
       android:text="@string/buttonRegister" />
  
</LinearLayout>

AndroidManifest.xml – Permission für den Zugriff auf das Internet einrichten

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.caprisoft.contactupload"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
     <uses-permission android:name="android.permission.INTERNET" /> 
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.