2015-03-31 38 views
2

我正在嘗試使用vk authmartini。但編譯出錯:社交網絡vk auth with martini

/goPath/vkAuthTry2.go:38: undefined: YourRedirectFunc 

問題是如何定義YourRedirectFunc函數。或者,如果問得更廣泛,我需要martini應用的工作示例,vk社交網絡身份驗證,或者更廣泛的使用vk身份驗證的任何golang網站的示例。

全碼:

package main 

import (
    "github.com/go-martini/martini" 
    "github.com/yanple/vk_api" 
    "net/http" 
) 

var api vk_api.Api 

func prepareMartini() *martini.ClassicMartini { 
    m := martini.Classic() 
    m.Get("/somePage", func(w http.ResponseWriter, r *http.Request) { 
     // And receive token on the special method (redirect uri) 
     currentUrl := r.URL.RequestURI() // for example "yoursite.com/get_access_token#access_token=3304fdb7c3b69ace6b055c6cba34e5e2f0229f7ac2ee4ef46dc9f0b241143bac993e6ced9a3fbc111111&expires_in=0&user_id=1" 
     accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(currentUrl) 
     if err != nil { 
      panic(err) 
     } 
     api.AccessToken = accessToken 
     api.UserId = userId 
     api.ExpiresIn = expiresIn 
     w.Write([]byte("somePage")) 
    }) 
    return m 
} 

func main() { 
    authUrl, err := api.GetAuthUrl(
     "domain.com/method_get_access_token", // redirect URI 
     "token",  // response type 
     "4672050",  // client id 
     "wall,offline", // permissions https://vk.com/dev/permissions 
    ) 
    if err != nil { 
     panic(err) 
    } 
    YourRedirectFunc(authUrl) 
    prepareMartini().Run() 
} 

更新

我根據@ Elwinar的答案編輯我的代碼:

package main 

import (
    "fmt" 
    "github.com/go-martini/martini" 
    "github.com/yanple/vk_api" 
    "net/http" 
) 

var api vk_api.Api 

func prepareMartini() *martini.ClassicMartini { 
    m := martini.Classic() 
    // This handler redirect the request to the vkontact system, which 
    // will perform the authentification then redirect the request to 
    // the URL we gave as the first paraemeter of the GetAuthUrl method 
    // (treated by the second handler) 
    m.Get("/vk/auth", func(w http.ResponseWriter, r *http.Request) { 
     var api vk_api.Api 
     authUrl, err := api.GetAuthUrl("http://localhost:3000/vk/token", "token", "4672050", "wall,offline") 
     if err != nil { 
      panic(err) 
     } 

     http.Redirect(w, r, authUrl, http.StatusFound) 
    }) 

    // This handler is the one that get the actual authentification 
    // information from the vkontact api. You get the access token, 
    // userid and expiration date of the authentification session. 
    // You can do whatever you want with them, generally storing them 
    // in session to be able to get the actual informations later using 
    // the access token. 
    m.Get("/vk/token", func(w http.ResponseWriter, r *http.Request) { 
     accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String()) 
     if err != nil { 
      panic(err) 
     } 
     fmt.Println(accessToken) 
     fmt.Println(userId) 
     fmt.Println(expiresIn) 
    }) 
    return m 
} 

func main() { 
    prepareMartini().Run() 
} 

現在沒有complie錯誤,但仍然無法登錄。 當我打開http://localhost:3000/vk/auth我網頁重定向...

https://oauth.vk.com/authorize?client_id=MY_APP_ID&redirect_uri=localhost%3A3000%2Fvk%2Ftoken&response_type=token&scope=wall%2Coffline 

...並得到以下瀏覽器輸出:

{"error":"invalid_request","error_description":"redirect_uri is incorrect, check application domain in the settings page"} 

當然代替4672050我貼我的應用程序ID。這個應用程序專門爲localhost:3000生成。 也許我需要粘貼一些我的私鑰for oauth,如pYFR2Xojlkad87880dLa

更新2

@ qwertmax的答案几乎可行。我已經成功登錄通過VK,但我的代碼打印空行,而不是userId和其他用戶信息:

accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String()) 

fmt.Println(accessToken) 
fmt.Println(userId) 
fmt.Println(expiresIn) 

回答

1

感謝您的回答, 我加了example @qwertmax並修復了url解析片段的bug。請更新包並查看示例。

package main 
// Thanks @qwertmax for this example 
// (http://stackoverflow.com/questions/29359907/social-network-vk-auth-with-martini) 


import (
    "log" 
    "github.com/go-martini/martini" 
    "github.com/yanple/vk_api" 
    "net/http" 
) 

var api vk_api.Api 

func prepareMartini() *martini.ClassicMartini { 
    m := martini.Classic() 

    m.Get("/vk/auth", func(w http.ResponseWriter, r *http.Request) { 
     authUrl, err := api.GetAuthUrl(
     "http://localhost:3000/vk/token", 
     "app client id", 
     "wall,offline") 

     if err != nil { 
      panic(err) 
     } 

     http.Redirect(w, r, authUrl, http.StatusFound) 
    }) 

    m.Get("/vk/token", func(w http.ResponseWriter, r *http.Request) { 
     code := r.URL.Query().Get("code") 

     err := api.OAuth(
     "http://localhost:3000/vk/token", // redirect uri 
     "app secret key", 
     "app client id", 
     code) 
     if err != nil { 
      panic(err) 
     } 
     http.Redirect(w, r, "/", http.StatusFound) 
    }) 

    m.Get("/", func(w http.ResponseWriter, r *http.Request) string { 
     if api.AccessToken == "" { 
      return "<a href='/vk/auth'>Авторизоваться</a>" 
     } 

     // Api have: AccessToken, UserId, ExpiresIn 
     log.Println("[LOG] martini.go:48 ->", api.AccessToken) 

     // Make query 
     params := make(map[string]string) 
     params["domain"] = "yanple" 
     params["count"] = "1" 

     strResp, err := api.Request("wall.get", params) 
     if err != nil { 
      panic(err) 
     } 
     return strResp 
    }) 
    return m 
} 

func main() { 
    prepareMartini().Run() 
} 

更新1: 更新你的包命令:去拿-u github.com/yanple/vk_api 感謝您的評論。

+1

爲了使這個例子工作,我不得不更新'vk_api'包:'go get -u github.com/yanple/vk_api' – 2015-05-28 04:03:51

0

在包文檔,YourRedirectFunc旨在作爲佔位符用於重定向請求的實際方法你特殊案例。例如,它可能是http.RedirectgetCurrentUrl也一樣。

事實上,你鏈接的例子應該寫成兩個處理您的馬提尼例如:

// This handler redirect the request to the vkontact system, which 
// will perform the authentification then redirect the request to 
// the URL we gave as the first paraemeter of the GetAuthUrl method 
// (treated by the second handler) 
m.Get("/vk/auth", func(w http.ResponseWriter, r *http.Request) { 
    var api vk_api.Api 
    authUrl, err := api.GetAuthUrl("domain.com/vk/token", "token", "4672050", "wall,offline") 
    if err != nil { 
     panic(err) 
    } 

    http.Redirect(w, r, authUrl, http.Found) 
}) 

// This handler is the one that get the actual authentification 
// information from the vkontact api. You get the access token, 
// userid and expiration date of the authentification session. 
// You can do whatever you want with them, generally storing them 
// in session to be able to get the actual informations later using 
// the access token. 
m.Get("/vk/token", func(w http.ResponseWriter, r *http.Request) { 
    accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String()) 
    if err != nil { 
     panic(err) 
    } 
}) 
+0

謝謝,它編譯的很好,但仍然無法登錄。請參閱我上面的更新。 – 2015-04-08 10:16:19

2
package main 

import (
    "fmt" 
    "github.com/go-martini/martini" 
    "github.com/yanple/vk_api" 
    "net/http" 
) 

var api vk_api.Api 

func prepareMartini() *martini.ClassicMartini { 
    m := martini.Classic() 

    m.Get("/vk/auth", func(w http.ResponseWriter, r *http.Request) { 
     var api vk_api.Api 
     authUrl, err := api.GetAuthUrl("http://localhost:3000/vk/token", "token", "2756549", "wall,offline") 

     fmt.Println(authUrl) 
     if err != nil { 
      panic(err) 
     } 

     http.Redirect(w, r, authUrl, http.StatusFound) 
    }) 

    m.Get("/vk/token", func(w http.ResponseWriter, r *http.Request) { 
     accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String()) 
     if err != nil { 
      panic(err) 
     } 
     fmt.Println(accessToken) 
     fmt.Println(userId) 
     fmt.Println(expiresIn) 
    }) 
    return m 
} 

func main() { 
    prepareMartini().Run() 
} 

你VK設置必須添加你的域名就像這個截圖

enter image description here

之後,你將被重定向到http://localhost:3000/vk/token#access_token=some_token&expires_in=0&user_id=0000000

但我不知道你將如何解析URL通過「ParseResponseUrl」,因爲VK得到你「片段URL」。

片段URL不發送通過HTTP服務 - 我認爲這可能是一個問題。

+0

謝謝,我已經登錄,但代碼打印空行'fmt.Println(accessToken) fmt.Println(userId) fmt.Println(expiresIn) '。請參閱上面的'更新2' – 2015-04-08 13:29:41

+0

是的,請參閱我的答案的結尾 - 這是因爲vk響應具有片段URL,#access_token ....等,它們不可見後端(用於您的服務器) – qwertmax 2015-04-08 13:36:34

+0

如果您打印r。 URL.String()你會看到/ vk/token,因爲在URL中#之後的所有內容都會停留在瀏覽器端(前端) – qwertmax 2015-04-08 13:38:17