<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" ><channel><title>Christoph Bünte&nbsp;&raquo; Software Entwicklung Berlin</title> <atom:link href="http://www.christophbuente.de/?s=meinvz%20verify%20signature%20ruby&#038;feed=rss2" rel="self" type="application/rss+xml" /><link>http://www.christophbuente.de</link> <description>Software Entwicklung</description> <lastBuildDate>Tue, 03 Aug 2010 15:37:30 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.0.1</generator> <item><title>Opensocial Gadgets &#8211; Apps für StudiVZ selbst entwickeln</title><link>http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/</link> <comments>http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/#comments</comments> <pubDate>Thu, 29 Oct 2009 19:39:51 +0000</pubDate> <dc:creator>Christoph Bünte</dc:creator> <category><![CDATA[Web Entwicklung]]></category> <category><![CDATA[backend]]></category> <category><![CDATA[beispiel]]></category> <category><![CDATA[example]]></category> <category><![CDATA[gadgets]]></category> <category><![CDATA[howto]]></category> <category><![CDATA[meinvz]]></category> <category><![CDATA[opensocial]]></category> <category><![CDATA[ruby]]></category> <category><![CDATA[Ruby on Rails]]></category> <category><![CDATA[schuelervz]]></category> <category><![CDATA[studivz]]></category> <category><![CDATA[Tutorial]]></category> <category><![CDATA[widgets]]></category><guid isPermaLink="false">http://www.christophbuente.de/?p=399</guid> <description><![CDATA[Wie StudiVZ bereits angekündigt hat, werden die ersten opensocial Anwendungen für ihre Plattform bald live gehen. Entwickler können sich schon jetzt registrieren und ihre so genannten Gadgets in einer Sandbox ausprobieren. Ich habe das Vergnügen für meinen aktuellen Kunden DaWanda ein Gadget für StudiVZ zu entwickeln. Ein Gadget besteht aus einer XML Datei, die definiert, [...]]]></description> <content:encoded><![CDATA[<p>Wie <a href="http://developer.studivz.net/2009/09/24/opensocial-is-now-available-in-our-vz-sandbox/">StudiVZ</a> bereits angekündigt hat, werden die ersten <a href="http://code.google.com/intl/de-DE/apis/opensocial/">opensocial</a> Anwendungen für ihre Plattform bald live gehen. Entwickler können sich schon jetzt registrieren und ihre so genannten Gadgets in einer Sandbox ausprobieren.</p><p>Ich habe das Vergnügen für meinen aktuellen Kunden <a href="http://www.dawanda.com">DaWanda</a> ein Gadget für StudiVZ zu entwickeln. Ein Gadget besteht aus einer XML Datei, die definiert, um welche Anwendung es sich handelt, wer der Author ist usw. Dazu gehören wahlweise mehrere CSS und Javascript Dateien. Nachdem man alles in eine Zip Datei, die den gleichen namen wie die XML Datei trägt, gepackt hat, kann man die Anwendung in die Sandbox hochladen und ausprobieren. Eine Beispiel Datei könnte so aussehen:</p><pre escaped="true" lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Module&gt;
  &lt;ModulePrefs
    title="Example StudiVZ Gadget"
    title_url="http://www.christophbuente.de"
    author="Christoph Bünte"
    author_email="info@christophbuente.de"
    description="Example description"
    screenshot="http://www.christophbuente.de/images/screenshot.jpg"
    thumbnail="http://www.christophbuente.de/images/thumbnail.jpg"&gt;
    &lt;Require feature="opensocial-0.8" /&gt;
    &lt;Require feature="views" /&gt;
  &lt;/ModulePrefs&gt;
  &lt;Content type="html" &gt;
    &lt;![CDATA[
      &lt;script&gt;
        function init() {
          // Put initialization code here
        }
        gadgets.util.registerOnLoadHandler(init);
      &lt;/script&gt;
    &lt;div id='container'&gt;&lt;/div&gt;
    ]]&gt;
  &lt;/Content&gt;
&lt;/Module&gt;</pre><p><span id="more-399"></span><br /> Jede Interaktion des Benutzers mit der Anwendung wird mit Hilfe weiterer Javascript Funktionen behandelt. Dazu stehen eine Reihe eingebauter Funktionen aus dem Opensocial Container bereit. Darüber hinaus haben die Entwickler von StudiVZ eine <a href="http://developer.studivz.net/wiki/index.php/Gadgets_API">API Beschreibung</a> der zusätzlichen Funktionen bereit gestellt. Was aber, wenn man nun nicht mit Javascript entwickeln möchte bzw. kann? Es besteht die Möglichkeit Flash Content einzubinden. Man kann aber auch ein beliebiges Backend einbinden. Dieses Backend muss nur 2 Bedingungen erfüllen:</p><ul><li>Es muss auf <acronym title="Hypertext Transfer Protocol">HTTP</acronym> Requests reagieren können und beliebiges <acronym title="Hypertext Markup Language">HTML</acronym>,<acronym title="Cascading Style Sheet">CSS</acronym> und JavaScript zurück liefern</li><li>Es muss im Namen des Applikationsbenutzers einen OAuth signierten Request an die StudiVZ <acronym title="Representational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym> schicken können.</li></ul><p><a href="http://www.christophbuente.de/wp-content/uploads/Bild-7.png"><img class="size-full wp-image-419 alignleft" title="Request Opensocial Backend" src="http://www.christophbuente.de/wp-content/uploads/Bild-7.png" alt="Schema: Request Opensocial Backend" width="348" height="376" /></a><br /> Wie im Schema zu sehen, sendet der User einen Request, um die Applikation zu benutzen. Der Container liest darauf hin den Inhalt der XML Datei aus. Dort ist neben einem DIV Container lediglich ein externes Javascript referenziert. In dem Javascript sind einfache Methoden zum Navigieren und Interagieren definiert. Das rendern des HTML übernimmt ein Ruby Backend. Das braucht zum Render unter Umständen noch zusätzliche Informationen wie zum Beispiel Name und Foto des Benuter usw. Diese Informationen holt es sich mit einem OAuth signierten Request von der abgebildeten REST API. Das vom Ruby Backend erzeugte HTML rendert der Opensocial Container in einem IFrame im Browser des Benutzers. Für eine bessere Übersicht definieren wir im XML einzelne Views, die jeweils einen eigenen Endpunkt im Backend haben. Eine einfache gadget.xml mit 2 definierten Views für Profil und Vollansicht mit Backend Anbindung:</p><pre escaped="true" lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Module&gt;
  &lt;ModulePrefs
    title="Spitzenmässiges StudiVZ Gadget mit Backendanbindung"
    title_url="http://www.christophbuente.de"
    author="Christoph Bünte"
    author_email="info@christophbuente.de"&gt;
    &lt;Require feature="opensocial-0.8" /&gt;
    &lt;Require feature="views" /&gt;
  &lt;/ModulePrefs&gt;
  &lt;Content type="html" view="profile" &gt;
    &lt;![CDATA[
      &lt;script type="text/javascript" src="http://www.yourbackend.com/profile.js" &gt;&lt;/script&gt;
      &lt;div id='profile'&gt;&lt;/div&gt;
    ]]&gt;
  &lt;/Content&gt;
  &lt;Content type="html" view="canvas" &gt;
    &lt;![CDATA[
      &lt;script type="text/javascript" src="http://www.yourbackend.com/canvas.js" &gt;&lt;/script&gt;
      &lt;div id='canvas'&gt;&lt;/div&gt;
    ]]&gt;
  &lt;/Content&gt;
&lt;/Module&gt;</pre><p>Das referenzierte Javascript ist ebenfalls sehr schlank. Darin wird lediglich eine Backend URL aufgerufen und deren Response Body in das profile bzw. canvas div geschrieben.</p><pre>function init{
  var url = 'http://www.yourbackend.com/profile/'
  var params = {};
  params[gadgets.io.RequestParameters.AUTHORIZATION]=gadgets.io.AuthorizationType.SIGNED;
  gadgets.io.makeRequest(url, requestCallback, params);

}

function requestCallback(obj) {
	document.getElementById('profile').innerHTML = obj.data;
}</pre><p>Damit die REST API benutzt werden kann, muss man sich an ihr Authentifizieren. Da das Backend aber dumm ist, hat es keine Userdaten, um sich dort anzumelden. Glücklicherweise ist der Request aus dem Javascript mit dem verschlüsselten Authentifierungsdaten des angemeldeten Anwendungsbenutzers signiert. Mit deren Hilfe können wir einen neuen, signierten Request erzeugen, den die API akzeptieren wird. Doch zuerst muss die Glültigkeit der Signatur überprüft werden:</p><p><code>sudo gem install oauth --source http://gemcutter.org</code></p><pre lang="ruby">
require 'oauth'
require 'oauth/consumer'
require 'oauth/request_proxy/action_controller_request'
require 'oauth/signature/rsa/sha1'
require 'oauth/signature/hmac/sha1'

class ApplicationController < ActionController::Base

  before_filter <img src='http://www.christophbuente.de/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> auth_required

  def oauth_required
    cert_file = File.join(RAILS_ROOT, 'public', 'public.cer')
    cert_str = File.read(cert_file)
    consumer = OAuth::Consumer.new(ConsumerToken, cert_str)

    begin
      pass = OAuth::Signature.build(request, :consumer => consumer).verify
      logger.info "Signature verification returned: #{pass}"
    rescue OAuth::Signature::UnknownSignatureMethod => e
      logger.error "ERROR "+ e.message
    end

    render :text => "OAuth access denied", :status => :unauthorized  unless pass
  end
</pre><p>Die URL für das öffentliche Zertifikat wird mit jedem Request mit geschickt. Einmal runterladen sollte reichen. Ich denke, man muss es nicht bei jedem Request erneut vom StudiVZ Server laden. Den Consumer Token findet ihr in der OAuth Section eurer Gadget Sandbox (http://www.meinvz.net/GadgetDeveloper/GadgetOAuth/xxx). xxx ist deine Gadget ID.</p><p>Sollte der before_filter nicht abbrechen war die Signatur korrekt und der Request kann bearbeitet werden. Aus einem mir nicht bekannten Grund ist der Request des Containers an das Backend mit der RSA-SHA1 Methode signiert. Dafür wird das Zertifikat benötigt. Für den Request an die API muss die HMAC-SHA1 Methode verwendet werden. Dafür wird ein neuer Consumer benötigt:</p><pre lang="ruby">def get_owner
  consumer = OAuth::Consumer.new(ConsumerToken, ConsumerSecret,
      :signature_method => 'HMAC-SHA1',
      :site => "http://sandbox.gadgets.apivz.net",
      :scheme => :query_string,
      :http_method => :get)
  requestor_param = {:xoauth_requestor_id => params[:opensocial_owner_id]}.to_param
  access_token = OAuth::AccessToken.new(consumer)
  response = access_token.get("/social/rest/people/#{params[:opensocial_owner_id]}/@self?#{requestor_param}")
  owner_attributes = JSON.parse(response.body)['entry']
end</pre><p>Feedback, Fragen und Kritik sind immer gerne willkommen.</p><div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2007-11-10-paypal-subscriptions-abonnements-in-java-integrieren/" rel="bookmark" class="crp_title">Paypal subscriptions &#8211; Abonnements in Java integrieren</a></li><li><a href="http://www.christophbuente.de/2010-07-20-rails-hosting-bei-rocket-rentals-auch-mit-staging-umgebung/" rel="bookmark" class="crp_title">Rails Hosting bei Rocket Rentals &#8211; auch mit Staging Umgebung</a></li><li><a href="http://www.christophbuente.de/2007-10-23-bots-aussperren-mit-captcha/" rel="bookmark" class="crp_title">captcha tutorial &#8211; Bots aussperren</a></li><li><a href="http://www.christophbuente.de/2007-12-06-voiceglue-installation-interactive-voice-response-leicht-gemacht/" rel="bookmark" class="crp_title">VoiceGlue Installation &#8211; Interactive Voice Response leicht gemacht</a></li><li><a href="http://www.christophbuente.de/2007-11-17-canoo-webtest-web-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">canoo webtest &#8211; Web-Anwendungen automatisch testen</a></li></ul></div>]]></content:encoded> <wfw:commentRss>http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using memcached
Page Caching using memcached
Database Caching 1/8 queries in 0.015 seconds using memcached
Object Caching 396/398 objects using memcached

Served from: www.christophbuente.de @ 2010-09-10 19:18:00 -->