2013-03-25 92 views
3

环境 - Python 2.7.3,webpy。通过python oauth2库的Github api v3访问 - 重定向问题

我想为使用Python web.py的github进行简单的oauth 3方式身份验证。根据github上的基本oauth指南,我正在做这样的事情:

import web,requests 
import oauth2,pymongo,json 
from oauth2client.client import OAuth2WebServerFlow 
urls=('/', 'githublogin', 
     '/session','session', 
     '/githubcallback','githubCallback'); 
class githublogin: 
    def GET(self): 
    new_url = 'https://github.com/login/oauth/authorize' 
    pay_load = {'client_id': '', 
       'client_secret':'', 
       'scope':'gist' 
       } 
    headers = {'content-type': 'application/json'} 
    r = requests.get(new_url, params=pay_load, headers=headers) 
    return r.content 

这是送我到GH登录页面。一旦我登录--GH没有将我重定向到回调。 redirect_uri参数在github应用程序中配置。我仔细检查过,以确保这是正确的。

class githubCallback: 
    def POST(self): 
    data = web.data() 
    print data 
    def GET(self): 
    print "callback called" 

而是在浏览器中我看到 http://<hostname>:8080/session 和404的消息,因为我还没有配置会话URL。这是没有问题1.问题没有2 - 如果我配置会话URL,并打印出来后消息

class session: 
    def POST(self): 
    data = web.data() 
     print data 
    def GET(self): 
     print "callback called" 

我可以看到张贴的东西叫做“authenticity_token”网址的一些数据。

我试过使用python_oauth2库,但无法通过authorization_url调用。所以我尝试了这个更简单的请求库。有人可以指出我这里出了什么问题。

+0

这是你正在遵循的指南:http://developer.github.com/guides/basics-of-authentication/?你在写什么“会话”?这是回调还是别的?此外,您不需要在初始请求中发送客户端密钥,只需发送客户端ID和范围,以及可选的重定向url:http://developer.github.com/v3/oauth/#web-application -流。您可以在回调处理程序中发送第二个请求中的客户端密钥。 – 2013-03-25 10:17:53

+0

@IvanZuzak - 这是使用'http:// developer.github.com/v3/oauth /#web-application-flow'的开发指南Im。 – 2013-03-25 10:26:04

+0

@IvanZuzak对不起,赶快输入这个开发指南使用'http://developer.github.com/v3/oauth /#web-application-flow'我发送没有client_secret的请求。同样的结果。 '/ session'是我在输入github用户名密码后在浏览器中看到的URL。 – 2013-03-25 10:32:29

回答

2

我不确定你的问题到底是什么,但试着重现下面的流程,首先手动使用浏览器,然后使用你的python库。它将帮助您调试问题。

  1. http://requestb.in/上创建请求bin。请求bin基本上是一个记录发送给它的所有HTTP请求的服务。您将使用此代替回调来记录正在发送到回调的内容。复制请求斌,这是一样的东西http://requestb.in/123a546b

  2. 转到您的OAuth应用程序安装在GitHub(https://github.com/settings/applications)的网址,输入您的特定应用程序的安装,并且回调URL设置为请求仓的网址你刚创建。

  3. 向GitHub OAuth页面发出请求,并定义client_id。只需在下面输入这个网址到浏览器,但改变YOUR_CLIENT_ID_HERE是您的OAuth应用程序的客户端ID:

    https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID_HERE

  4. 输入您的用户名和密码,然后单击授权。然后,GitHub的应用程序将您重定向到您创建的请求仓服务,并在浏览器的URL应该是这样的(注意代码查询参数):

    http://requestb.in/YOUR_REQUEST_BIN_ID?code=GITHUB_CODE

    (例如,http://requestb.in/abc1def2?code=123a456b789cdef

    另外,浏览器中页面的内容应该是“ok”(这是请求bin服务返回的内容)。

  5. 转到您创建的请求bin页面并刷新它。您现在将看到GitHub OAuth服务器发送给您的HTTP GET请求的日志条目以及所有HTTP标头。基本上,您会看到与您重定向到的URL中存在相同的代码参数。如果你得到这个参数,你现在愿意与这个代码和客户端密钥POST请求,因为在引导步骤2中使用的是:http://developer.github.com/v3/oauth/#web-application-flow

让我知道如果任何这些步骤对您造成问题。

+0

这个流程很完美。我在python流程中做的几乎是一样的,而且是扯皮。感谢您的投入。我会看看Python库出了什么问题。 – 2013-03-25 11:21:22

+0

这真的很奇怪。我建议你也尝试使用普通的Python HTTP库来发送HTTP请求,就像你通过浏览器(例如http://docs.python-requests.org/en/latest/)一样发送HTTP请求,或者使用一个用于GitHub的Python库通常可以正确处理OAuth流(http://developer.github.com/v3/libraries/#python)。无论如何,让我们知道你什么时候发现了什么bug :)。 – 2013-03-25 11:26:21

+0

我正在使用python请求库。但是这次我做了一个简单的改变。我不是从服务器发送登录请求,而是从HTML页面发送,使用模板呈现。这工作。我将在答案部分进一步阐述。 – 2013-03-25 16:09:20

3

所以这里是我如何解决这个问题。感谢@Ivanzuzak提供的requestb.in提示。

我正在使用Python webpy。

import web,requests 
import oauth2,json 
urls=('/', 'githublogin', 
     '/githubcallback','githubCallback'); 
render = web.template.render('templates/') 
class githublogin: 
    def GET(self): 
    client_id = '' 
    url_string = "https://github.com/login/oauth/authorize?client_id=" + client_id 
    return render.index(url_string) 

class githubCallback: 
    def GET(self): 
    data = json.loads(json.dumps(web.input())) 
    print data['code'] 
    headers = {'content-type': 'application/json'} 
    pay_load = {'client_id': '', 
       'client_secret':'', 
       'code' : data['code'] } 
    r = requests.post('https://github.com/login/oauth/access_token', data=json.dumps(pay_load), headers=headers) 
    token_temp = r.text.split('&') 
    token = token_temp[0].split('=') 
    access_token = token[1] 
    repo_url = 'https://api.github.com/user?access_token=' + access_token 
    response = requests.get(repo_url) 
    final_data = response.content 
    print final_data 

app = web.application(urls,globals()) 
if __name__ == "__main__": 
    app.run() 

我以前没有使用html文件,而是直接从githublogin类发送请求。这没有用。在这里,我使用html来指导用户从他登录到gh的地方开始。有了这个,我添加了一个html,并使用templator呈现它。

def with (parameter) 
<html> 
    <head> 
    </head> 
    <body> 
    <p>Well, hello there!</p> 
    <p>We're going to now talk to the GitHub API. Ready? <a href=$parameter>Click here</a> to begin!</a></p> 
    <p>If that link doesn't work, remember to provide your own <a href="http://developer.github.com/v3/oauth/#web-application-flow">Client ID</a>!</p> 
    </body> 
</html> 

该文件直接从开发指南中获取,只改变了client_id参数。

另一点需要注意的是,在requests.post方法中 - 直接传递pay_load不起作用。它必须使用json.dumps进行序列化。