|
1
|
+from datetime import datetime
|
1
|
2
|
from logging import error
|
2
|
3
|
from flasgger import swag_from
|
3
|
4
|
from app.util import BlueprintApi
|
...
|
...
|
@@ -6,7 +7,7 @@ from .models import * |
6
|
7
|
from .oauth2 import authorization, generate_user_info, require_oauth
|
7
|
8
|
from authlib.oauth2 import OAuth2Error
|
8
|
9
|
from authlib.integrations.flask_oauth2 import current_token
|
9
|
|
-from . import user_create, client_create, client_query, user_query, user_update, user_delete
|
|
10
|
+from . import user_create, client_create, client_query, user_query, user_update, user_delete, auth_log_query
|
10
|
11
|
import configure
|
11
|
12
|
from app.decorators.auth_decorator import auth_decorator
|
12
|
13
|
import time
|
...
|
...
|
@@ -15,7 +16,8 @@ from app.util.component.StructurePrint import StructurePrint |
15
|
16
|
import traceback
|
16
|
17
|
from oauthlib import oauth2
|
17
|
18
|
import requests
|
18
|
|
-from app.modules.auth.models import OAuth2Token, User, db
|
|
19
|
+from app.modules.auth.models import OAuth2Token, User, db, OAuthLog
|
|
20
|
+from app.util.enum.AuthEnum import AuthEnum, OriginEnum, OperateEnum
|
19
|
21
|
|
20
|
22
|
|
21
|
23
|
def current_user():
|
...
|
...
|
@@ -45,7 +47,7 @@ class DataManager(BlueprintApi): |
45
|
47
|
request2 = authorization.create_oauth2_request(request)
|
46
|
48
|
grant2 = authorization.get_authorization_grant(request=request2)
|
47
|
49
|
redirect_uri = grant2.validate_authorization_request()
|
48
|
|
- session["redirect_uri"] = redirect_uri
|
|
50
|
+ session["redirect_uri"] = redirect_uri # 记录跳转重定向地址
|
49
|
51
|
if request.method == "GET":
|
50
|
52
|
# 没有登录,跳转到登录界面
|
51
|
53
|
try:
|
...
|
...
|
@@ -71,8 +73,11 @@ class DataManager(BlueprintApi): |
71
|
73
|
crypt_pwd = request.form.get("password")
|
72
|
74
|
# password = SM3.encode(crypt_pwd)
|
73
|
75
|
password = SM3.encode(AESHelper.decode(crypt_pwd))
|
|
76
|
+
|
|
77
|
+ # 仅支持dmap平台保留用户登录
|
|
78
|
+ origin_type = OriginEnum.Dmap.name.lower()
|
74
|
79
|
user = User.query.filter_by(
|
75
|
|
- username=username, password=password).first()
|
|
80
|
+ username=username, password=password, origin=origin_type).first()
|
76
|
81
|
if not user:
|
77
|
82
|
error = "账号或密码不正确"
|
78
|
83
|
flash(error)
|
...
|
...
|
@@ -83,6 +88,15 @@ class DataManager(BlueprintApi): |
83
|
88
|
if user:
|
84
|
89
|
session["id"] = user.id
|
85
|
90
|
grant_user = user
|
|
91
|
+
|
|
92
|
+ # 日志
|
|
93
|
+ log = OAuthLog(user_id=user.id, username=user.username,
|
|
94
|
+ auth_type=AuthEnum.Other.name.lower(),
|
|
95
|
+ message="认证成功", create_time=datetime.now(),
|
|
96
|
+ operate_type=OperateEnum.Login)
|
|
97
|
+ db.session.add(log)
|
|
98
|
+ db.session.commit()
|
|
99
|
+
|
86
|
100
|
return authorization.create_authorization_response(request=request, grant_user=grant_user)
|
87
|
101
|
|
88
|
102
|
# try:
|
...
|
...
|
@@ -116,14 +130,25 @@ class DataManager(BlueprintApi): |
116
|
130
|
def logout():
|
117
|
131
|
try:
|
118
|
132
|
request2 = authorization.create_oauth2_request(request)
|
119
|
|
- grant1 = authorization.get_authorization_grant(request=request2)
|
|
133
|
+ grant1 = authorization.get_authorization_grant(
|
|
134
|
+ request=request2)
|
120
|
135
|
redirect_uri = grant1.validate_authorization_request()
|
121
|
136
|
access_token = request.args.get("accesstoken")
|
122
|
137
|
accesstoken = OAuth2Token.query.filter_by(
|
123
|
138
|
access_token=access_token).first()
|
124
|
139
|
accesstoken.revoked = True
|
125
|
140
|
db.session.commit()
|
|
141
|
+ user = current_user()
|
126
|
142
|
remove_user()
|
|
143
|
+
|
|
144
|
+ # 日志
|
|
145
|
+ log = OAuthLog(user_id=user.id, username=user.username,
|
|
146
|
+ auth_type=AuthEnum.Other.name.lower(),
|
|
147
|
+ message="注销成功", create_time=datetime.now(),
|
|
148
|
+ operate_type=OperateEnum.Logout, token=access_token)
|
|
149
|
+ db.session.add(log)
|
|
150
|
+ db.session.commit()
|
|
151
|
+
|
127
|
152
|
except OAuth2Error as error:
|
128
|
153
|
return jsonify(dict(error.get_body()))
|
129
|
154
|
return redirect(redirect_uri)
|
...
|
...
|
@@ -207,15 +232,15 @@ class DataManager(BlueprintApi): |
207
|
232
|
except Exception as e:
|
208
|
233
|
StructurePrint().print(e.__str__()+":" + traceback.format_exc(), "error")
|
209
|
234
|
|
210
|
|
- @staticmethod
|
211
|
|
- @bp.route("/translate", methods=["GET"])
|
212
|
|
- def translate():
|
213
|
|
- password = ['esri@123', 'admin', 'DMap@123', 'passwd']
|
214
|
|
- result = {}
|
215
|
|
- for p in password:
|
216
|
|
- new_pwd = SM3.encode(p)
|
217
|
|
- result[p] = new_pwd
|
218
|
|
- return result
|
|
235
|
+ # @staticmethod
|
|
236
|
+ # @bp.route("/translate", methods=["GET"])
|
|
237
|
+ # def translate():
|
|
238
|
+ # password = ['esri@123', 'admin', 'DMap@123', 'passwd','dci112..']
|
|
239
|
+ # result = {}
|
|
240
|
+ # for p in password:
|
|
241
|
+ # new_pwd = SM3.encode(p)
|
|
242
|
+ # result[p] = new_pwd
|
|
243
|
+ # return result
|
219
|
244
|
|
220
|
245
|
'''
|
221
|
246
|
三方登录:OA
|
...
|
...
|
@@ -237,78 +262,109 @@ class DataManager(BlueprintApi): |
237
|
262
|
@staticmethod
|
238
|
263
|
@bp.route("/oa/callback", methods=["GET"])
|
239
|
264
|
def oa_callback():
|
|
265
|
+ try:
|
|
266
|
+ client = oauth2.WebApplicationClient(
|
|
267
|
+ configure.OA["client_id"])
|
|
268
|
+
|
|
269
|
+ # 获取code
|
|
270
|
+ code = client.parse_request_uri_response(
|
|
271
|
+ request.url, session["oauth_state"]).get("code")
|
|
272
|
+
|
|
273
|
+ if code == None:
|
|
274
|
+ return "登录失败"
|
|
275
|
+
|
|
276
|
+ # 获取token
|
|
277
|
+ body = client.prepare_request_body(
|
|
278
|
+ code, redirect_uri=configure.OA["redirect_uri"], client_secret=configure.OA["client_secret"])
|
|
279
|
+
|
|
280
|
+ r = requests.post(configure.OA["token_endpoint"], body, headers={
|
|
281
|
+ "Content-Type": "application/x-www-form-urlencoded"})
|
|
282
|
+
|
|
283
|
+ tokeninfo = r.json()
|
|
284
|
+ access_token = tokeninfo.get("access_token")
|
|
285
|
+ id_token = tokeninfo.get("id_token")
|
|
286
|
+
|
|
287
|
+ auth_default_redirect_uri = configure.auth_default_redirect_uri
|
|
288
|
+ origin_type = "dci_oa" # 三方登录标识
|
|
289
|
+ if access_token:
|
|
290
|
+ # 获取用户信息
|
|
291
|
+ userinfo_url = configure.OA["userinfo_endpoint"]
|
|
292
|
+ user_request = requests.get(userinfo_url, headers={
|
|
293
|
+ "Authorization": "Bearer %s" % access_token})
|
|
294
|
+ userinfo = user_request.json()
|
|
295
|
+ user_name = userinfo.get("user_name")
|
|
296
|
+ display_name = userinfo.get("displayname")
|
|
297
|
+ display_name = display_name.split(
|
|
298
|
+ )[-1] if display_name != None else user_name
|
|
299
|
+
|
|
300
|
+ # 默认关联dmap用户
|
|
301
|
+ try:
|
|
302
|
+ user = User.query.filter_by(
|
|
303
|
+ username=user_name, origin=origin_type).first()
|
|
304
|
+ except error as e:
|
|
305
|
+ user = None
|
|
306
|
+
|
|
307
|
+ # 用户不存在,创建用户
|
240
|
308
|
|
241
|
|
- client = oauth2.WebApplicationClient(
|
242
|
|
- configure.OA["client_id"])
|
243
|
|
-
|
244
|
|
- # 获取code
|
245
|
|
- code = client.parse_request_uri_response(
|
246
|
|
- request.url, session["oauth_state"]).get("code")
|
247
|
|
-
|
248
|
|
- if code == None:
|
249
|
|
- return "登录失败"
|
250
|
|
-
|
251
|
|
- # 获取token
|
252
|
|
- body = client.prepare_request_body(
|
253
|
|
- code, redirect_uri=configure.OA["redirect_uri"], client_secret=configure.OA["client_secret"])
|
254
|
|
-
|
255
|
|
- r = requests.post(configure.OA["token_endpoint"], body, headers={
|
256
|
|
- "Content-Type": "application/x-www-form-urlencoded"})
|
257
|
|
-
|
258
|
|
- tokeninfo = r.json()
|
259
|
|
- access_token = tokeninfo.get("access_token")
|
|
309
|
+ if not user:
|
|
310
|
+ user = User(username=user_name, password=SM3.encode('DMap@123'), role='dataman',
|
|
311
|
+ phone='', company='', position='', email='', displayname=display_name,
|
|
312
|
+ origin=origin_type,
|
|
313
|
+ create_time=time.strftime(
|
|
314
|
+ "%Y-%m-%d %H:%M:%S", time.localtime()),
|
|
315
|
+ update_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
|
|
316
|
+ db.session.add(user)
|
|
317
|
+ db.session.commit()
|
|
318
|
+
|
|
319
|
+ session["id"] = user.id
|
|
320
|
+
|
|
321
|
+ # dmap token授权
|
|
322
|
+ # 存入数据库
|
|
323
|
+ token = OAuth2Token(
|
|
324
|
+ client_id=configure.OA["client_id"],
|
|
325
|
+ token_type=tokeninfo.get("token_type"),
|
|
326
|
+ access_token=access_token,
|
|
327
|
+ scope=tokeninfo.get("scope"),
|
|
328
|
+ expires_in=tokeninfo.get("expires_in"),
|
|
329
|
+ user_id=user.id
|
|
330
|
+ )
|
|
331
|
+
|
|
332
|
+ db.session.add(token)
|
|
333
|
+ db.session.commit()
|
260
|
334
|
|
261
|
|
- if access_token:
|
262
|
|
- # 获取用户信息
|
263
|
|
- userinfo_url = configure.OA["userinfo_endpoint"]
|
264
|
|
- user_request = requests.get(userinfo_url, headers={
|
265
|
|
- "Authorization": "Bearer %s" % access_token})
|
266
|
|
- userinfo = user_request.json()
|
267
|
|
- user_name = userinfo.get("user_name")
|
268
|
|
- display_name = userinfo.get("displayname")
|
|
335
|
+ redirect_uri = session["redirect_uri"] if "redirect_uri" in session else auth_default_redirect_uri
|
269
|
336
|
|
270
|
|
- # 默认关联dmap用户
|
271
|
|
- try:
|
272
|
|
- user = User.query.filter_by(
|
273
|
|
- username=user_name).first()
|
274
|
|
- except error as e:
|
275
|
|
- user = None
|
|
337
|
+ #session["id_token"] = id_token
|
|
338
|
+ response = make_response(redirect(redirect_uri))
|
|
339
|
+ response.set_cookie('accessToken', access_token,
|
|
340
|
+ max_age=configure.expiretime)
|
|
341
|
+ response.set_cookie('id_token', id_token,
|
|
342
|
+ max_age=configure.expiretime)
|
276
|
343
|
|
277
|
|
- # 用户不存在,创建用户
|
278
|
|
- if not user:
|
279
|
|
- user = User(username=user_name, password=SM3.encode('DMap@123'), role='dataman',
|
280
|
|
- phone='', company='', position='', email='',
|
281
|
|
- create_time=time.strftime(
|
282
|
|
- "%Y-%m-%d %H:%M:%S", time.localtime()),
|
283
|
|
- update_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
|
284
|
|
- db.session.add(user)
|
|
344
|
+ log = OAuthLog(user_id=user.id, username=user_name, auth_type=AuthEnum.Other.name.lower(),
|
|
345
|
+ message="三方认证成功", create_time=datetime.now(),
|
|
346
|
+ operate_type=OperateEnum.Login, token=access_token)
|
|
347
|
+ db.session.add(log)
|
285
|
348
|
db.session.commit()
|
286
|
349
|
|
287
|
|
- # dmap token授权
|
288
|
|
- session["id"] = user.id
|
|
350
|
+ return response
|
|
351
|
+ else:
|
|
352
|
+ raise Exception("缺少access_token")
|
289
|
353
|
|
290
|
|
- # 存入数据库
|
291
|
|
- token = OAuth2Token(
|
292
|
|
- client_id=configure.OA["client_id"],
|
293
|
|
- token_type=tokeninfo.get("token_type"),
|
294
|
|
- access_token=access_token,
|
295
|
|
- scope=tokeninfo.get("scope"),
|
296
|
|
- expires_in=tokeninfo.get("expires_in"),
|
297
|
|
- user_id=user.id
|
298
|
|
- )
|
299
|
|
- db.session.add(token)
|
300
|
|
- db.session.commit()
|
301
|
|
- redirect_uri = ""
|
302
|
|
- try:
|
303
|
|
- redirect_uri = session["redirect_uri"]
|
304
|
|
- if not redirect_uri:
|
305
|
|
- redirect_uri = '/'
|
306
|
|
- except:
|
307
|
|
- redirect_uri = "/"
|
308
|
|
-
|
309
|
|
- response = make_response(redirect(redirect_uri))
|
310
|
|
- response.set_cookie('accessToken', access_token, max_age=604_800)
|
311
|
|
-
|
312
|
|
- return response
|
313
|
|
- else:
|
314
|
|
- return redirect('/') |
|
354
|
+ except Exception as e:
|
|
355
|
+ StructurePrint().print(e.__str__()+":" + traceback.format_exc(), "error")
|
|
356
|
+ pop_list = ["id", "redirect_uri"]
|
|
357
|
+ for p in pop_list:
|
|
358
|
+ if p in session:
|
|
359
|
+ session.pop(p)
|
|
360
|
+ return redirect(auth_default_redirect_uri)
|
|
361
|
+
|
|
362
|
+ @staticmethod
|
|
363
|
+ @bp.route("/logs", methods=["GET"])
|
|
364
|
+ @swag_from(auth_log_query.Api.api_doc)
|
|
365
|
+ @auth_decorator(configure.UserPermission)
|
|
366
|
+ def authLog():
|
|
367
|
+ '''
|
|
368
|
+ 登录日志
|
|
369
|
+ '''
|
|
370
|
+ return auth_log_query.Api().result |
...
|
...
|
|