社交网络 vk auth with martini

social network vk auth with martini

我正在尝试使用 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()
}

现在没有编译错误,但仍然无法登录。 当我打开 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"}

当然,我粘贴了我的应用程序 ID,而不是 4672050。这个应用程序是专门为 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)

在包文档中,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)
    }
})
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 发送服务 - 我认为这可能是个问题。

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

package main
// Thanks @qwertmax for this example
// (


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 感谢评论。