2014年1月9日 星期四

Google App Engine 使用Facebook帳號登入

上一篇「Google App Engine 連接資料庫(GAE Datastore)」已經有學習過如何將資料寫進資料庫中了,現在要來學習如何使用Facebook做登入動作,並且取得使用者FB的相關資訊。

首先,先到Facebook開發者平台這邊註冊一個應用程式
https://developers.facebook.com/



















之後會要求輸入Display Name、Namespace,Display Name是可以輸入中文,然後用來當作標題之類的文字,Namespace就有點像是id,不能跟別人重複的唯一識別碼。














之後會導到該應用程式的管理頁面,會看到應用程式編號應用程式密鑰等資訊






























左方有一個設定,我們必須去裡面新增平台,由於GAE是屬於網頁的應用程式,所以我們要選擇新增網頁,在網站URL那邊打上網域,因為目前我們是在自己的電腦測試,所以網域僅要打上http://127.0.0.1:8888/即可,之後上架到GAE則需要改成http://yourAppname.appspot.com/































之後回到Eclipse開始來建立專案

主要由以下這幾個檔案組成:

FunctionCall.java (將所有的Java功能全部寫在這個裡面,可以做呼叫)
PMF.java (主要是要使用到PersistenceManagerFactory這功能)
store.java (這個檔案有點類似像資料庫中的資料表)
hello.jsp (這頁包含一個簡單的Link,連結到FB)
login.jsp (這要主要是與FB做溝通,來取得相關資料的)

FunctionCall.java

package com.FBconnect.study2fun;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.jdo.Query;
import javax.jdo.PersistenceManager;

public class FunctionCall {

 public static void adddata(String name){
  //宣告一個PersistenceManager
  PersistenceManager pm = PMF.get().getPersistenceManager();
  //創建一個資料表物件,並同時將資料寫入
  store db = new store(name);
  try{
   //透過PersistenceManager將資料表放入DataStore
   pm.makePersistent(db);
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   pm.close();
  }
 }
 
 //這邊是一個查詢功能,會資料料庫中的所有FBid的list回傳
 public static List<store> queryFBid(){
  PersistenceManager pm = PMF.get().getPersistenceManager();
  //此處可以做query的動作,有點類似SQL語法
  Query query = pm.newQuery(store.class);
  List<store> result = (List<store>) query.execute();
   return result;
    
  
 } 
 //將FB回傳的網址解析出來
 public static String geturl(String url){
  StringBuilder sb = new StringBuilder();
  try{
   URL graphURL = new URL(url);
   HttpURLConnection conn = (HttpURLConnection)graphURL.openConnection();
   BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
   String line = in.readLine();
  while(line !=null){
   sb.append(line);
   line = in.readLine();
  }
  
  }catch(MalformedURLException e){
   e.printStackTrace();
  }catch(IOException e){
   e.printStackTrace();
  }
  return sb.toString();
 }
}

PMF.java

package com.study2fun.datastore;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public class PMF {

 private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");
 private PMF(){}
 public static PersistenceManagerFactory get(){
  return pmfInstance;
 }
}


store.java

package com.FBconnect.study2fun;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

//這個地方有點像一個資料表的意思
@PersistenceCapable(identityType=IdentityType.APPLICATION)
public class store {

 //可以設定主鍵,這邊是讓系統自動產生流水號
 @PrimaryKey
 @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
 Long id;
 
 //各欄位的名稱和屬性
 @Persistent
 String FBid;
  
 //各欄位的名稱和屬性
 //@Persistent
 //int No;
 
 //設定建構子,將值傳進來
 public store(String name){
  super();
  this.FBid = name;
 }
 
 
 public Long get_id(){return id;}
 public String get_FBid(){return FBid;}
 

}




hello.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@page import="com.FBconnect.study2fun.FunctionCall"%>
<%@page import="com.FBconnect.study2fun.store"%>
<%@page import="java.util.List"%>
<%@page import="com.restfb.types.User" %>
<%@page import="com.restfb.DefaultFacebookClient" %>
<%@page import="com.restfb.FacebookClient" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>FBconnect</title>
</head>

<body>
<%
//這邊是一個debug的技巧,雖然程式是在網頁上面跑,但是在Console那邊還是可以檢視到System.out.println的資料,就可以知道程式是否有執行到這邊了
System.out.println("test-show");
//取得授權碼
String code = request.getParameter("code");
//應用程式ID
String client_id = "562850973805812";
//程式密鑰
String secret = "f752230afd606dd0f386246e06fc9b48";
String redirect_uri = "http://127.0.0.1:8888/hello.jsp";
String authURL = "https://graph.facebook.com/oauth/access_token?"+
"client_id="+ client_id+
"&redirect_uri="+redirect_uri+
"&client_secret="+secret+
"&code="+code;
String resp = FunctionCall.geturl(authURL);
String access_token = resp.substring(resp.indexOf("=")+1,resp.lastIndexOf("&"));
FacebookClient fbClient = new DefaultFacebookClient(access_token);
User user = fbClient.fetchObject("me",User.class);
//這邊的話,因為FB的資訊不僅有id而已,還有其他的資訊,生日、Email等等,這些資訊皆可以抓取,雖然有時好像抓不太到~"~
String name = user.getName();
//這邊我們將取得的FBid寫進到我們的資料庫中
FunctionCall.adddata(name);
%>
<!--  下面這邊要直接印出一個變數,可以直接用個=變數即可-->
Hello, <%=name %><p>

<p>資料庫中所有的FBid如下<p>
<%
List<store> result = FunctionCall.queryFBid();
for(store fs : result){
 //如果在Java Code裡面要包含網頁語法的話,就可以使用out.println,用字串的方式輸出網頁語法來呈現
 out.println(fs.get_FBid()+"<p>");
  }
%>



</body>
</html>


login.jsp

<%@ page language="java" contentType="text/html; charset=BIG5"
    pageEncoding="BIG5"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
<title>Insert title here</title>
</head>
<body>
<!-- 使用FB登入的方式便是透過一個FB的連結去取得驗證 -->
<%
String fbloginurl = "https://www.facebook.com/dialog/oauth?"+
"client_id=562850973805812" +
"&redirect_uri=http://127.0.0.1:8888/hello.jsp";
%>
<a href="<%=fbloginurl %>">Facebook登入</a>

</body>
</html>

一開始我們先到登入頁面














之後會跳到FB那邊取得授權



















最後會到達轉址後的頁面(前提是授權要過,接受的意思)























其實像最後一步這邊,可以寫一個簡單的功能去判斷,該使用者是否已經有記錄過登入資訊了,如果已經有記錄過的話就不用再將他寫進資料庫裡面了。

完整專案檔下載:下載


沒有留言:

張貼留言