0%

python - google oauth2 登陆

最近业务用上了google oauth2登陆,google文档写的很详细,在python flask很容易就能实现oauth2登陆.
oauth2的原理一张图就能概括:
webflow.png

需要用到的库:
The Google APIs Client Library for Python:

1
pip install --upgrade google-api-python-client

The google-auth, google-auth-oauthlib, and google-auth-httplib2 for user authorization.

1
pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2

下面贴一下关键代码(省略了很多无关的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#登陆界面
@app.route('/index')
def login_index():
return render_template('login.html')

#登陆
@app.route('/login', methods=['GET', 'POST'])
def login():
if 'credentials' not in session:
#首先要获取凭据,调用授权方法
return redirect(url_for('authorize'))

credentials = google.oauth2.credentials.Credentials(
**session['credentials'])

#到这里就授权成功,可以通过authed_session来调用google api
authed_session = AuthorizedSession(credentials)

#调用google api 获取授权用户的信息
response = authed_session.get('https://www.googleapis.com/userinfo/v2/me')
user = json.loads(response.text)
#用户账号存入session
session['user'] = user['email']
#返回登陆成功页面
return render_template('success.html')

#注销
@app.route('/logout')
def logout():
if 'credentials' not in session:
return redirect(url_for('login_index'))
credentials = google.oauth2.credentials.Credentials(
**session['credentials'])
try:
# 注销凭据需要传入一个凭据token参数然后post到相应的api地址
revoke = requests.post('https://accounts.google.com/o/oauth2/revoke',
params={'token': credentials.token},
headers={'content-type': 'application/x-www-form-urlencoded'})

status_code = getattr(revoke, 'status_code')
#注销成功后删除用户登陆session
del session['user']
if status_code == 200:
#删除session中的凭据
del session['credentials']
flash('Logout successful!', 'success')
return render_template('login.html')
except Exception as e:
app.logger.info(e)

#授权
@app.route('/authorize')
def authorize():
#这里需要一个在google cloud 平台申请的一个凭据密钥,client_secret.json
#需要到https://console.cloud.google.com/apis/credentials申请
CLIENT_SECRETS_FILE = app.config['CLIENT_SECRETS_FILE']
#需要申请的权限范围
SCOPES = app.config['SCOPES']
#回调地址
REDIRECT_URI = app.config['REDIRECT_URI']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE, scopes=SCOPES)

flow.redirect_uri = REDIRECT_URI
authorization_url, state = flow.authorization_url(
access_type='offline',
include_granted_scopes='true')
session['state'] = state
return redirect(authorization_url)

#授权成功后的回调函数
@app.route('/oauth2callback')
def oauth2callback():
try:
state = session['state']
CLIENT_SECRETS_FILE = app.config['CLIENT_SECRETS_FILE']
SCOPES = app.config['SCOPES']
REDIRECT_URI = app.config['REDIRECT_URI']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
flow.redirect_uri = REDIRECT_URI
authorization_response = request.url
#获取授权token
flow.fetch_token(authorization_response=authorization_response)
credentials = flow.credentials
#存储凭据到session
session['credentials'] = credentials_to_dict(credentials)
except Exception as e:
if 'credentials' in session:
del session['credentials']
app.logger.info(e)
return redirect(url_for('login_index'))
return redirect(url_for('login'))


def credentials_to_dict(credentials):
return {'token': credentials.token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes}