auth.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. # -*- coding: utf-8 -*-
  2. from fastapi import APIRouter, Depends, Request, Header, Form, Body
  3. from fastapi.responses import FileResponse, StreamingResponse
  4. from sqlalchemy.orm import Session
  5. from database import get_db
  6. from utils import *
  7. from utils.vcode import *
  8. from utils.redis_util import *
  9. import base64
  10. from common.const import *
  11. from io import BytesIO
  12. from utils.StripTagsHTMLParser import *
  13. from common import security
  14. from datetime import timedelta
  15. from common.security import valid_access_token
  16. from common.auth_user import *
  17. from common import YzyApi
  18. from models import *
  19. from urllib.parse import quote
  20. import requests
  21. router = APIRouter()
  22. @router.get('/tenant/list')
  23. async def tenant_list(
  24. request: Request,
  25. db: Session = Depends(get_db)
  26. ):
  27. return {
  28. "code": 200,
  29. "msg": "操作成功",
  30. "data": {
  31. "tenantEnabled": False,
  32. "voList": []
  33. }
  34. }
  35. def buildVerificationCodeRedisKey(uuid: str) -> str:
  36. return VERIFICATION_CODE_REDIS_PREFIX.format(uuid)
  37. @router.get('/code')
  38. async def code(
  39. request: Request,
  40. db: Session = Depends(get_db)
  41. ):
  42. uuid_str = md5(new_guid())
  43. image, code = getVerifyCode()
  44. buf = BytesIO()
  45. image.save(buf, 'png')
  46. img_data = buf.getvalue()
  47. image_bytes_io = BytesIO(img_data)
  48. image_bytes_io.seek(0)
  49. image_bytes = image_bytes_io.read()
  50. base64_str = base64.b64encode(image_bytes).decode('utf-8')
  51. redis_key = "kaptcha_" + buildVerificationCodeRedisKey(uuid_str)
  52. redis_set(redis_key, code)
  53. return {
  54. "code": 200,
  55. "msg": "操作成功",
  56. "data": {
  57. "captchaEnabled": True,
  58. "uuid": uuid_str,
  59. "img": base64_str
  60. }
  61. }
  62. @router.post('/login')
  63. async def login(
  64. request: Request,
  65. db: Session = Depends(get_db),
  66. data: dict = Depends(remove_xss_json)
  67. ):
  68. tenantId = data['tenantId']
  69. username = data['username']
  70. password = data['password']
  71. rememberMe = data['rememberMe']
  72. uuid_str = data['uuid']
  73. code = data['code']
  74. clientId = data['clientId']
  75. grantType = data['grantType']
  76. uuid = buildVerificationCodeRedisKey(uuid_str)
  77. redis_key = "kaptcha_" + uuid
  78. redis_code = redis_get(redis_key)
  79. if code is None or code != redis_code:
  80. return {
  81. "code": 500,
  82. "msg": "图片验证码不正确",
  83. }
  84. redis_login_key = "login_user_" + username
  85. login_error_times = redis_get(redis_login_key)
  86. if login_error_times is None:
  87. login_error_times = 0
  88. else:
  89. login_error_times = int(login_error_times)
  90. if login_error_times >= 5:
  91. return {
  92. "code": 500,
  93. "msg": "登录错误多,请5分钟后再尝试!",
  94. }
  95. # userpass = ase_utils.aesDecrypt(loginkey, userpass)
  96. row = db.query(SysUser).filter(SysUser.user_name == username).first()
  97. if row is None:
  98. login_error_times = login_error_times + 1
  99. redis_set_with_time(redis_login_key, str(login_error_times), 300)
  100. return {
  101. "error": 1,
  102. "errmsg": "帐号或者密码错误",
  103. }
  104. '''
  105. m = hashlib.md5()
  106. m.update(userpass.encode('utf-8'))
  107. password_md5 = m.hexdigest()
  108. password_db = row.password
  109. if password_md5 != password_db:
  110. login_error_times = login_error_times + 1
  111. redis_set_with_time(redis_login_key, str(login_error_times), 300)
  112. return {
  113. "error": 1,
  114. "errmsg": "帐号或者密码错误",
  115. }
  116. # 校验长期(超过1个月)未使用的账号和及开通后未及时(如72小时)修改初始密码的账号做清除
  117. last_login_time = datetime.fromtimestamp(row.last_login_time)
  118. if row.login == 0:
  119. # 计算初始化的时间和当前时间相差的小时数
  120. diff_hour = (datetime.now() - last_login_time).seconds/3600
  121. if diff_hour > 72:
  122. return {
  123. "error": 1,
  124. "errmsg": "你的账号在开通后(72小时)内未登录及修改初始密码,账号已被锁定,请联系管理员处理,否则将被清除。",
  125. }
  126. else:
  127. # 计算上次登录到当前时间的相差天数
  128. diff_day = (datetime.now() - last_login_time).days
  129. if diff_day > 30:
  130. return {
  131. "error": 1,
  132. "errmsg": "你的账号在超过30天未登录使用,账号已被锁定,请联系管理员处理,否则将被清除。",
  133. }
  134. redis_set_with_time(redis_login_key, str(0), 1)
  135. '''
  136. user_id = str(row.user_id)
  137. auth = {
  138. "user_id": user_id,
  139. "user_name": row.user_name,
  140. "nick_name": row.nick_name,
  141. "is_yzy_user": "0"
  142. }
  143. request.session['user_auth'] = auth
  144. request.session['user_auth_sign'] = data_auth_sign(auth)
  145. request.session['user_name'] = username
  146. # db_czrz_serv.log_username(db, row.uid, row.username, "登录", "后台管理账号+密码登录成功", request.client.host)
  147. row.login_date = datetime.now()
  148. row.login_ip = request.client.host
  149. # row.login = row.login + 1
  150. db.commit()
  151. access_token_expires = timedelta(seconds = 7200)
  152. access_token = security.create_access_token(
  153. data={"sub": user_id}, expires_delta = access_token_expires
  154. )
  155. refresh_token_expires = timedelta(seconds = 7200)
  156. refresh_token = security.create_access_token(
  157. data={"sub": user_id}, expires_delta = refresh_token_expires
  158. )
  159. return {
  160. "code": 200,
  161. "msg": "操作成功",
  162. "data": {
  163. "access_token": access_token,
  164. "refresh_token": refresh_token,
  165. "expire_in": 7200,
  166. "refresh_expire_in": 7200,
  167. "client_id": clientId,
  168. "scope": "",
  169. "openid": ""
  170. }
  171. }
  172. @router.post('/logout')
  173. async def logout(
  174. request: Request,
  175. db: Session = Depends(get_db),
  176. user: AuthUser = Depends(get_auth_user)
  177. ):
  178. logger.info("logout ok")
  179. request.session.clear()
  180. try:
  181. if user.is_yzy_user == 1:
  182. logout_url = settings.TYRZ_LOGOUT.format(settings.TYRZ_CLIENT_ID) + quote(settings.HOME_URL+"/yjzp/")
  183. logger.info(logout_url)
  184. else:
  185. logout_url = settings.HOME_URL + "/yjzp/"
  186. except:
  187. logout_url = settings.HOME_URL+"/yjzp/"
  188. return {
  189. "code": 200,
  190. "msg": "退出成功",
  191. "data": logout_url
  192. }
  193. # 小屏专用
  194. @router.post('/yzy/callback')
  195. async def yzy(
  196. request: Request,
  197. db: Session = Depends(get_db),
  198. data: dict = Depends(remove_xss_json)
  199. ):
  200. code = data['code']
  201. state = data['state']
  202. state_str = base64.b64decode(state).decode('utf-8')
  203. state_json = json.loads(state_str)
  204. print(code, state_json)
  205. if len(code) < 30:
  206. resp = YzyApi.get_user_info(code)
  207. if resp['errcode'] != 0:
  208. return {
  209. "code": 500,
  210. "msg": "Code异常"
  211. }
  212. user_id = resp['UserId']
  213. else:
  214. from utils import ase_utils
  215. user_id = ase_utils.aesDecrypt(md5("c9128dee-912c-11ef-bf07-00ff257b5fc6"), code)
  216. # user_id = "eb4kehgy6wj4qn0jhx1dk6"
  217. row = db.query(YzyOrgUserEntity).filter(YzyOrgUserEntity.userid == user_id).first()
  218. if row is None:
  219. return {
  220. "code": 500,
  221. "msg": "user_id异常"
  222. }
  223. yzy_account = row.account
  224. row = db.query(SysUser).filter(SysUser.yzy_account == yzy_account).first()
  225. if row is None:
  226. return {
  227. "code": 500,
  228. "msg": "用户不是本系统用户"
  229. }
  230. user_id = str(row.user_id)
  231. access_token_expires = timedelta(seconds = 7200)
  232. access_token = security.create_access_token(
  233. data={"sub": user_id}, expires_delta = access_token_expires
  234. )
  235. refresh_token_expires = timedelta(seconds = 7200)
  236. refresh_token = security.create_access_token(
  237. data={"sub": user_id}, expires_delta = refresh_token_expires
  238. )
  239. return {
  240. "code": 200,
  241. "msg": "粤政易登录成功",
  242. "data": {
  243. "access_token": access_token,
  244. "refresh_token": refresh_token,
  245. "expire_in": 7200,
  246. "refresh_expire_in": 7200,
  247. "scope": "",
  248. "redirect_url": state_json['redirect_url']
  249. }
  250. }
  251. # 粤政易token登录
  252. @router.post('/yzylogin')
  253. async def login(
  254. request: Request,
  255. data: dict = Depends(remove_xss_json),
  256. db: Session = Depends(get_db)
  257. ):
  258. code = data['code']
  259. redis_key = "yzy_" + code
  260. user_id = redis_get(redis_key)
  261. if user_id is None:
  262. return {
  263. "code": 500,
  264. "msg": "用户不是本系统用户"
  265. }
  266. row = db.query(SysUser).filter(SysUser.user_id == int(user_id)).first()
  267. if row is None:
  268. return {
  269. "code": 500,
  270. "msg": "用户不是本系统用户"
  271. }
  272. user_id = str(row.user_id)
  273. auth = {
  274. "user_id": user_id,
  275. "user_name": row.user_name,
  276. "nick_name": row.nick_name,
  277. "is_yzy_user": "1"
  278. }
  279. request.session['user_auth'] = auth
  280. request.session['user_auth_sign'] = data_auth_sign(auth)
  281. request.session['user_name'] = row.user_name
  282. # db_czrz_serv.log_username(db, row.uid, row.username, "登录", "后台管理账号+密码登录成功", request.client.host)
  283. row.login_date = datetime.now()
  284. row.login_ip = request.client.host
  285. # row.login = row.login + 1
  286. db.commit()
  287. access_token_expires = timedelta(seconds = 7200)
  288. access_token = security.create_access_token(
  289. data={"sub": user_id}, expires_delta = access_token_expires
  290. )
  291. refresh_token_expires = timedelta(seconds = 7200)
  292. refresh_token = security.create_access_token(
  293. data={"sub": user_id}, expires_delta = refresh_token_expires
  294. )
  295. return {
  296. "code": 200,
  297. "msg": "操作成功",
  298. "data": {
  299. "access_token": access_token,
  300. "refresh_token": refresh_token,
  301. "expire_in": 7200,
  302. "refresh_expire_in": 7200,
  303. "client_id": 0,
  304. "scope": "",
  305. "openid": ""
  306. }
  307. }