英文:
social network vk auth with martini
问题
我正在尝试在martini中使用vk auth。但在编译时出现错误:
/goPath/vkAuthTry2.go:38: undefined: YourRedirectFunc
问题是如何定义YourRedirectFunc
函数。或者更广泛地说,我需要一个使用vk
社交网络身份验证的martini
应用的工作示例,或者更广泛地说,任何使用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"}
当然,我将4672050
替换为我的应用程序ID。这个应用程序是专门为localhost:3000
生成的。
也许我需要在某个地方粘贴我的私钥,例如pYFR2Xojlkad87880dLa
。
更新2:
@qwertmax的答案几乎可以工作。我已经成功通过vk登录,但是我的代码打印出空行,而不是userId
和其他用户信息:
accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String())
fmt.Println(accessToken)
fmt.Println(userId)
fmt.Println(expiresIn)
英文:
I am trying to use vk auth with martini. But have error on compile:
/goPath/vkAuthTry2.go:38: undefined: YourRedirectFunc
The question is how to define YourRedirectFunc
function. Or if ask more widely I need working example of martini
app with vk
social network authentication or if even more widely an example of any golang website using vk
authentication.
Full code:
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()
}
Update
I edited my code according to @Elwinar's answer:
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()
}
now no complie errors, but still cannot login.
When I opened http://localhost:3000/vk/auth
I was redirected on page...
https://oauth.vk.com/authorize?client_id=MY_APP_ID&redirect_uri=localhost%3A3000%2Fvk%2Ftoken&response_type=token&scope=wall%2Coffline
... and got the following browser output:
{"error":"invalid_request","error_description":"redirect_uri is incorrect, check application domain in the settings page"}
Of course instead of 4672050
I pasted my app id. This app was specially generated for localhost:3000
.
Maybe I need to paste somewhere my private key for oauth like pYFR2Xojlkad87880dLa
.
Update 2
@qwertmax's answer almost works. I have successfully logged in by vk, but my code prints empty lines instead of userId
and another user information:
accessToken, userId, expiresIn, err := vk_api.ParseResponseUrl(r.URL.String())
fmt.Println(accessToken)
fmt.Println(userId)
fmt.Println(expiresIn)
答案1
得分: 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"。
"fragment URL" 不会通过 HTTP 发送到服务器,我认为这可能是个问题。
英文:
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()
}
for you VK settings you have to add your domain like on this screenshot
After that you will be redirected to http://localhost:3000/vk/token#access_token=some_token&expires_in=0&user_id=0000000
but I'm not sure how you will Parse url via "ParseResponseUrl" because vk get to you "fragment url".
Fragment url is not sending to serve via HTTP - I think that could be a problem.
答案2
得分: 1
感谢回答,
我添加了 示例 @qwertmax,并修复了解析 URL 片段的错误。请更新包并查看示例。
package main
// 感谢 @qwertmax 提供的示例
// (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**
感谢您的评论。
<details>
<summary>英文:</summary>
Thanks for answer,
I added [example](https://github.com/yanple/vk_api/blob/master/examples/martini.go) @qwertmax and fixed bug for parse fragment of url. Please update package and see example.
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()
}
**Update 1:**
Update your package with command: **go get -u github.com/yanple/vk_api**
Thanks for the comment.
</details>
# 答案3
**得分**: 0
在包文档中,`YourRedirectFunc`被用作在你的特定情况下重定向请求的实际方法的占位符。例如,它可以是`http.Redirect`。`getCurrentUrl`也是同样的情况。
实际上,你提供的示例应该写成两个处理程序,用于你的martini实例:
```go
// 这个处理程序将请求重定向到vkontakte系统,该系统将执行身份验证,然后将请求重定向到我们在GetAuthUrl方法的第一个参数中提供的URL(由第二个处理程序处理)
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)
})
// 这个处理程序从vkontakte api获取实际的身份验证信息。你可以获取访问令牌、用户ID和身份验证会话的过期日期。你可以根据需要对它们进行任何操作,通常是将它们存储在会话中,以便以后使用访问令牌获取实际的信息。
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)
}
})
英文:
In the package documentation, YourRedirectFunc
is intended as placeholder for the actual method used to redirect a request in your particular case. It could be http.Redirect
for example. Same for getCurrentUrl
.
In fact, the example you linked to should be written as two handlers for your martini instance:
// 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)
}
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论