2012-04-22 93 views
15

我一直在寻找2天的答案,但没有出现。Python Oauth2 - 用Google登录

我正在尝试在Django上集成Oauth2来与Google进行登录。我有的代码会引发异常 - “令牌无效”。

出现这种情况:

resp, content = client.request(access_token_url, "POST") 
    if resp['status'] != '200': 
     print content 
     raise Exception("Invalid response from Google."+content) 
在google_authenticate

()

请帮助我。

我的代码:

def google_login(request): 
    scope = "https://www.googleapis.com/auth/userinfo.profile" 

    request_token_url = "https://www.google.com/accounts/OAuthGetRequestToken?scope=%s" % scope 
    authorize_url = 'https://www.google.com/accounts/OAuthAuthorizeToken' 
    authenticate_url = "https://accounts.google.com/o/oauth2/auth" 

    response_type = "code" 
    redirect_uri = "http://127.0.0.1:8000/login/google/auth" 
    scope = "https://www.googleapis.com/auth/userinfo.profile" 

    oauth_key = settings.GOOGLE_KEY 
    oauth_secret = settings.GOOGLE_SECRET 

    consumer = oauth.Consumer(oauth_key, oauth_secret) 
    client = oauth.Client(consumer) 

    # Step 1: Get a request token. This is a temporary token that is used for 
    # having the user authorize an access token and to sign the request to obtain 
    # said access token. 

    resp, content = client.request(request_token_url, "POST") 
    request_token = dict(urlparse.parse_qsl(content)) 

    if resp['status'] != '200': 
     raise Exception("Invalid response from Google.") 

    # Step 2. Store the request token in a session for later use. 
    request.session['request_token'] = dict(cgi.parse_qsl(content)) 

    # Step 3. Redirect the user to the authentication URL. 
    url = "%s?oauth_token=%s&client_id=%s&response_type=%s&redirect_uri=%s&scope=%s" % (authenticate_url, 
     request.session['request_token']['oauth_token'], 
     oauth_key,response_type,redirect_uri,scope) 

    return HttpResponseRedirect(url) 

def google_authenticate(request): 
    access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken' 

    oauth_key = settings.GOOGLE_KEY 
    oauth_secret = settings.GOOGLE_SECRET 

    consumer = oauth.Consumer(oauth_key, oauth_secret) 

    # Step 1. Use the request token in the session to build a new client. 
    token = oauth.Token(request.session['request_token']['oauth_token'], 
     request.session['request_token']['oauth_token_secret']) 
    if 'oauth_verifier' in request.GET: 
     token.set_verifier(request.GET['oauth_verifier']) 
    client = oauth.Client(consumer, token) 

    # Step 2. Request the authorized access token from Google. 
    resp, content = client.request(access_token_url, "POST") 
    if resp['status'] != '200': 
     print content 
     raise Exception("Invalid response from Google."+content) 

    access_token = dict(cgi.parse_qsl(content)) 

    # Step 3. Lookup the user or create them if they don't exist. 
    try: 
     user = User.objects.get(username=access_token['screen_name']) 
    except User.DoesNotExist: 
     # When creating the user I just use their [email protected] 
     # for their email and the oauth_token_secret for their password. 
     # These two things will likely never be used. Alternatively, you 
     # can prompt them for their email here. Either way, the password 
     # should never be used. 
     user = User.objects.create_user(access_token['screen_name'], 
      '%[email protected]' % access_token['screen_name'], 
      access_token['oauth_token_secret']) 

     # Save our permanent token and secret for later. 
     profile = Profile() 
     profile.user = user 
     profile.oauth_token = access_token['oauth_token'] 
     profile.oauth_secret = access_token['oauth_token_secret'] 
     profile.save() 

    # Authenticate the user and log them in using Django's pre-built 
    # functions for these things. 
    user = authenticate(username=access_token['screen_name'], 
     password=access_token['oauth_token_secret']) 
    login(request, user) 

    return HttpResponseRedirect('/') 

回答

23

后很长一段时间,又花了白白浪费掉很多时间,我放弃了与OAuth2用户,因为它是难以配置,以及所有我需要的是登录用户。下面的代码应该可以帮助需要做类似的事情并且可以自定义的人。我所做的一切都是按照这样在这里形成的网址和说明 - >https://developers.google.com/accounts/docs/OAuth2Login

我做了两个视图(任何人都不能使用Django - 网页),并做了一个链接到第一种: 此页我打电话登录/谷歌,并从登录页面链接到它。

def google_login(request): 
    token_request_uri = "https://accounts.google.com/o/oauth2/auth" 
    response_type = "code" 
    client_id = XXXXXX-your_client_id 
    redirect_uri = "http://mysite/login/google/auth" 
    scope = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email" 
    url = "{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}".format(
     token_request_uri = token_request_uri, 
     response_type = response_type, 
     client_id = client_id, 
     redirect_uri = redirect_uri, 
     scope = scope) 
    return HttpResponseRedirect(url) 

上述代码重定向到第二页(此页面必须定义为google应用定义中的重定向uri)。 我叫这个页面登录/谷歌/ AUTH:

def google_authenticate(request): 
    parser = Http() 
    login_failed_url = '/' 
    if 'error' in request.GET or 'code' not in request.GET: 
     return HttpResponseRedirect('{loginfailed}'.format(loginfailed = login_failed_url)) 

    access_token_uri = 'https://accounts.google.com/o/oauth2/token' 
    redirect_uri = "http://mysite/login/google/auth" 
    params = urllib.urlencode({ 
     'code':request.GET['code'], 
     'redirect_uri':redirect_uri, 
     'client_id':XXXXX_your_google_key, 
     'client_secret':XXXXX_your_google_secret, 
     'grant_type':'authorization_code' 
    }) 
    headers={'content-type':'application/x-www-form-urlencoded'} 
    resp, content = parser.request(access_token_uri, method = 'POST', body = params, headers = headers) 
    token_data = jsonDecode(content) 
    resp, content = parser.request("https://www.googleapis.com/oauth2/v1/userinfo?access_token={accessToken}".format(accessToken=token_data['access_token'])) 
    #this gets the google profile!! 
    google_profile = jsonDecode(content) 
    #log the user in--> 
    #HERE YOU LOG THE USER IN, OR ANYTHING ELSE YOU WANT 
    #THEN REDIRECT TO PROTECTED PAGE 
    return HttpResponseRedirect('/dashboard') 

我真的希望这有助于人在那里,并保存到我浪费了时间。对代码的评论比欢迎!

+7

如果有人想知道,现在有来自谷歌的oauth2client库实现流和存储凭据=>现在需要10行全部 https://developers.google.com/api-client-library/python/ guide/aaa_oauth http://code.google.com/p/google-api-python-client/source/browse/#hg%2Fsamples%2Fdjango_sample – lajarre 2012-10-02 18:28:45

+1

@ user1160475查看developers.google.com。您应该已经拥有Google用户名和密码,请登录。 – Meir 2014-09-18 06:23:34

+0

谢谢。代码有效。花了我一些时间来弄清楚httplib2中定义了Http()类。 – 2014-09-23 12:33:54