2

我正在尝试将vk authmartini一起使用。但是编译时出错:

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

问题是如何定义YourRedirectFunc功能。或者,如果问得更广泛,我需要martini使用社交网络身份验证的应用程序示例,或者更广泛地需要vk使用身份验证的任何 golang 网站的示例vk

完整代码:

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()
}

现在没有编译错误,但仍然无法登录。当我打开时,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. 也许我需要将我的私钥粘贴到 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)
4

3 回答 3

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 设置,您必须像在此屏幕截图中一样添加您的域

在此处输入图像描述

之后,您将被重定向到http://localhost:3000/vk/token#access_token=some_token&expires_in=0&user_id=0000000

但我不确定你将如何通过“ParseResponseUrl”解析 url,因为 vk 会找到你的“fragment url”。

片段 url 没有通过 HTTP 发送到服务 - 我认为这可能是一个问题。

于 2015-04-08T11:38:21.880 回答
1

感谢您的回答,我添加了示例@qwertmax 并修复了解析 url 片段的错误。请更新软件包并查看示例。

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: 使用命令更新您的包:go get -u github.com/yanple/vk_api 感谢您的评论。

于 2015-05-27T14:33:17.633 回答
0

在包文档中,YourRedirectFunc旨在作为用于在您的特定情况下重定向请求的实际方法的占位符。可以是http.Redirect例如。对getCurrentUrl.

实际上,您链接到的示例应该编写为您的 martini 实例的两个处理程序:

// 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)
    }
})
于 2015-04-08T09:25:07.243 回答