2012-04-22 85 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