python實現(xiàn)微博oauth2認證


主要流程:

實現(xiàn)OAuth 2.0流程:編寫B(tài)ottle路由來處理授權(quán)請求玄坦、回調(diào)和令牌交換敬尺。

JWT處理:在用戶通過OAuth驗證后肢执,生成JWT并將其發(fā)送給客戶端。后續(xù)請求可以使用JWT進行身份驗證。


# !/usr/bin/env python3

# -*- coding: utf-8 -*-


import requests

import json

import jwt

import os

from datetime import datetime, timedelta

from http import HTTPStatus

from bottle import Bottle, request, response, redirect, template, static_file, run

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

app = Bottle()

# 生成一個隨機的32長度的密鑰

# JWT_SECRET_KEY = os.urandom(32)

JWT_SECRET_KEY = '9q8w7e60asjhywe4f1qaz2wsx9jkseduc4rfv'.encode()

COOKIE_SECRET = '9q8w7e6r1a2s3d4f'

COOKIE_KEY = "X-Auth-Cookie"

CLIENT_ID = '384983687214'

CLIENT_SECRET = 'b1fboo33bgb827427bf119apad882412'

AUTHORIZATION_URL = 'https://api.weibo.com/oauth2/authorize'

ACCESS_TOKEN_URL = 'https://api.weibo.com/oauth2/access_token'

USER_INFO_URL = 'https://api.weibo.com/oauth2/get_token_info'

# REDIRECT_URL = 'http://localhost:5000/callback'

# REDIRECT_URL = 'http://localhost:8001/user/callback'

# REDIRECT_URL = 'http://localhost:8001/user/localLogin'

# REDIRECT_URL = 'https://b97b-223-112-131-202.ngrok-free.app/api/vdi-server/user/localLogin'

REDIRECT_URL = 'https://5111-112-81-204-118.ngrok-free.app/callback'

@app.route('/')

def index():

? ? # 已登錄 瀏覽器使用cookie校驗 或瀏覽器客戶端均使用token

? ? cookie_value = request.get_cookie(COOKIE_KEY, secret=COOKIE_SECRET)

? ? print('cookie_value=', cookie_value)

? ? if cookie_value:

? ? ? ? # 校驗cookie

? ? ? ? return template('''

? ? ? ? <html>

? ? ? ? <body>

? ? ? ? ? ? <h1>Welcome, {{cookie_value}}!</h1>

? ? ? ? </body>

? ? ? ? </html>

? ? ? ? ''', cookie_value=cookie_value)

? ? # 未登錄 構(gòu)造授權(quán)鏈接

? ? auth_url = f"{AUTHORIZATION_URL}?client_id={CLIENT_ID}&response_type=code&redirect_uri={REDIRECT_URL}&state=terminal_or_admin_id"

? ? return template('''

? ? <html>

? ? <body>

? ? ? ? <h4>auth_url, {{auth_url}}!</h4>

? ? ? ? <a href="{{auth_url}}">Login with WeiBo</a>

? ? </body>

? ? </html>

? ? ''', auth_url=auth_url)

? ? # print(auth_url)

? ? # redirect(auth_url)

@app.route('/callback')

def app_redirect():

? ? # 從WeiBo獲取code

? ? query = request.query

? ? print('code_request_url=', request.url)

? ? print(query, type(query))

? ? code = query.get('code')

? ? if not code:

? ? ? ? print('params code not found!')

? ? ? ? return template('''?

? ? ? ? <html>?

? ? ? ? <body>?

? ? ? ? ? ? <h1>Welcome, {{login}}!</h1>

? ? ? ? </body>?

? ? ? ? </html>?

? ? ? ? ''', login='NOT FOUND')

? ? print('code=', code)

? ? print('state=', query.get('state'))

? ? # 使用code獲取access_token

? ? data = {

? ? ? ? 'client_id': CLIENT_ID,

? ? ? ? 'client_secret': CLIENT_SECRET,

? ? ? ? 'grant_type': 'authorization_code',

? ? ? ? 'redirect_uri': REDIRECT_URL,

? ? ? ? 'code': code,

? ? }

? ? headers = {'Accept': 'application/json'}

? ? res = requests.post(ACCESS_TOKEN_URL, params=data, headers=headers, verify=False, timeout=5)

? ? print('request url', request.url)

? ? if res.status_code != HTTPStatus.OK:

? ? ? ? print('request token error', res.status_code)

? ? ? ? return

? ? print('res.json() = ', res.json())

? ? access_token = res.json().get('access_token')

? ? print('access_token=', access_token)

? ? # 使用access_token獲取用戶信息

? ? # headers = {'Authorization': f'token {access_token}'}

? ? user_url = f"{USER_INFO_URL}?access_token={access_token}"

? ? user_res = requests.post(user_url, verify=False, timeout=5)

? ? if user_res.status_code != HTTPStatus.OK:

? ? ? ? print('request user error', user_res.status_code)

? ? ? ? return

? ? user_data = user_res.json()

? ? # 方式一 瀏覽器可設(shè)置cookie? 或客戶端和客戶端均使用token jwt等

? ? response.set_cookie(COOKIE_KEY, user_data['uid'], secret=COOKIE_SECRET, max_age=6000)

? ? # 方式二 生成JWT

? ? jwt_token = generate_jwt(user_data['uid'], user_data['uid'])

? ? user_data['jwt'] = jwt_token

? ? print(user_data)

? ? # return user_data

? ? # demo直接顯示用戶信息 實際應(yīng)返回token或jwt 客戶端或瀏覽器存儲 每次接口訪問攜帶過來

? ? return template('''

? ? <html>

? ? <body>

? ? ? ? <h1>Welcome, {{uid}}!</h1>

? ? ? ? <p>Your WeiBo id is {{uid}}.</p>

? ? ? ? <p>Your WeiBo login is {{uid}}.</p>

? ? ? ? <p>Your Jwt token is {{jwt}}.</p>

? ? </body>

? ? </html>

? ? ''', **user_data)

# 生成JWT的函數(shù)

def generate_jwt(user_id, user_name, expiration_time=3600):

? ? payload = {

? ? ? ? 'user_id': user_id,

? ? ? ? 'user_name': user_name,

? ? ? ? 'exp': datetime.utcnow() + timedelta(seconds=expiration_time),

? ? ? ? 'iat': datetime.utcnow()

? ? }

? ? return jwt.encode(payload, JWT_SECRET_KEY, algorithm='HS256')

# 簡單的JWT驗證示例(需要額外路由處理JWT驗證)

@app.route('/protected')

def protected():

? ? token = request.headers.get('Authorization')

? ? if not token:

? ? ? ? return "JWT token is missing"

? ? try:

? ? ? ? payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=['HS256'])

? ? ? ? return f"Welcome, {payload['user_name']}!"

? ? except jwt.ExpiredSignatureError:

? ? ? ? return "The token has expired"

? ? except jwt.InvalidTokenError:

? ? ? ? return "Invalid token"

if __name__ == '__main__':

? ? run(app, host='localhost', port=5000)




最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末技掏,一起剝皮案震驚了整個濱河市铃将,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哑梳,老刑警劉巖麸塞,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涧衙,居然都是意外死亡,警方通過查閱死者的電腦和手機奥此,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門弧哎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稚虎,你說我怎么就攤上這事撤嫩。” “怎么了蠢终?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵序攘,是天一觀的道長。 經(jīng)常有香客問我寻拂,道長程奠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任祭钉,我火速辦了婚禮瞄沙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘慌核。我一直安慰自己距境,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布垮卓。 她就那樣靜靜地躺著垫桂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粟按。 梳的紋絲不亂的頭發(fā)上诬滩,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音灭将,去河邊找鬼碱呼。 笑死,一個胖子當著我的面吹牛宗侦,可吹牛的內(nèi)容都是我干的愚臀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼矾利,長吁一口氣:“原來是場噩夢啊……” “哼姑裂!你這毒婦竟也來了馋袜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤舶斧,失蹤者是張志新(化名)和其女友劉穎欣鳖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茴厉,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡泽台,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了矾缓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怀酷。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嗜闻,靈堂內(nèi)的尸體忽然破棺而出蜕依,到底是詐尸還是另有隱情,我是刑警寧澤琉雳,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布样眠,位于F島的核電站,受9級特大地震影響翠肘,放射性物質(zhì)發(fā)生泄漏檐束。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一束倍、第九天 我趴在偏房一處隱蔽的房頂上張望厢塘。 院中可真熱鬧,春花似錦肌幽、人聲如沸晚碾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽格嘁。三九已至,卻和暖如春廊移,著一層夾襖步出監(jiān)牢的瞬間糕簿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工狡孔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留懂诗,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓苗膝,卻偏偏與公主長得像殃恒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355