auth.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. router = APIRouter()
  20. @router.get('/tenant/list')
  21. async def tenant_list(
  22. request: Request,
  23. db: Session = Depends(get_db)
  24. ):
  25. return {
  26. "code": 200,
  27. "msg": "操作成功",
  28. "data": {
  29. "tenantEnabled": False,
  30. "voList": []
  31. }
  32. }
  33. def buildVerificationCodeRedisKey(uuid: str) -> str:
  34. return VERIFICATION_CODE_REDIS_PREFIX.format(uuid)
  35. @router.get('/code')
  36. async def code(
  37. request: Request,
  38. db: Session = Depends(get_db)
  39. ):
  40. uuid_str = md5(new_guid())
  41. image, code = getVerifyCode()
  42. buf = BytesIO()
  43. image.save(buf, 'png')
  44. img_data = buf.getvalue()
  45. image_bytes_io = BytesIO(img_data)
  46. image_bytes_io.seek(0)
  47. image_bytes = image_bytes_io.read()
  48. base64_str = base64.b64encode(image_bytes).decode('utf-8')
  49. redis_key = "kaptcha_" + buildVerificationCodeRedisKey(uuid_str)
  50. redis_set(redis_key, code)
  51. return {
  52. "code": 200,
  53. "msg": "操作成功",
  54. "data": {
  55. "captchaEnabled": True,
  56. "uuid": uuid_str,
  57. "img": base64_str
  58. }
  59. }
  60. @router.post('/login')
  61. async def login(
  62. request: Request,
  63. db: Session = Depends(get_db),
  64. data: dict = Depends(remove_xss_json)
  65. ):
  66. tenantId = data['tenantId']
  67. username = data['username']
  68. password = data['password']
  69. rememberMe = data['rememberMe']
  70. uuid_str = data['uuid']
  71. code = data['code']
  72. clientId = data['clientId']
  73. grantType = data['grantType']
  74. uuid = buildVerificationCodeRedisKey(uuid_str)
  75. redis_key = "kaptcha_" + uuid
  76. redis_code = redis_get(redis_key)
  77. if code is None or code != redis_code:
  78. return {
  79. "code": 500,
  80. "msg": "图片验证码不正确",
  81. }
  82. redis_login_key = "login_user_" + username
  83. login_error_times = redis_get(redis_login_key)
  84. if login_error_times is None:
  85. login_error_times = 0
  86. else:
  87. login_error_times = int(login_error_times)
  88. if login_error_times >= 5:
  89. return {
  90. "code": 500,
  91. "msg": "登录错误多,请5分钟后再尝试!",
  92. }
  93. # userpass = ase_utils.aesDecrypt(loginkey, userpass)
  94. row = db.query(SysUser).filter(SysUser.user_name == username).first()
  95. if row is None:
  96. login_error_times = login_error_times + 1
  97. redis_set_with_time(redis_login_key, str(login_error_times), 300)
  98. return {
  99. "error": 1,
  100. "errmsg": "帐号或者密码错误",
  101. }
  102. '''
  103. m = hashlib.md5()
  104. m.update(userpass.encode('utf-8'))
  105. password_md5 = m.hexdigest()
  106. password_db = row.password
  107. if password_md5 != password_db:
  108. login_error_times = login_error_times + 1
  109. redis_set_with_time(redis_login_key, str(login_error_times), 300)
  110. return {
  111. "error": 1,
  112. "errmsg": "帐号或者密码错误",
  113. }
  114. # 校验长期(超过1个月)未使用的账号和及开通后未及时(如72小时)修改初始密码的账号做清除
  115. last_login_time = datetime.fromtimestamp(row.last_login_time)
  116. if row.login == 0:
  117. # 计算初始化的时间和当前时间相差的小时数
  118. diff_hour = (datetime.now() - last_login_time).seconds/3600
  119. if diff_hour > 72:
  120. return {
  121. "error": 1,
  122. "errmsg": "你的账号在开通后(72小时)内未登录及修改初始密码,账号已被锁定,请联系管理员处理,否则将被清除。",
  123. }
  124. else:
  125. # 计算上次登录到当前时间的相差天数
  126. diff_day = (datetime.now() - last_login_time).days
  127. if diff_day > 30:
  128. return {
  129. "error": 1,
  130. "errmsg": "你的账号在超过30天未登录使用,账号已被锁定,请联系管理员处理,否则将被清除。",
  131. }
  132. redis_set_with_time(redis_login_key, str(0), 1)
  133. '''
  134. user_id = str(row.user_id)
  135. auth = {
  136. "user_id": user_id,
  137. "user_name": row.user_name,
  138. "nick_name": row.nick_name,
  139. "is_yzy_user": "0"
  140. }
  141. request.session['user_auth'] = auth
  142. request.session['user_auth_sign'] = data_auth_sign(auth)
  143. request.session['user_name'] = username
  144. # db_czrz_serv.log_username(db, row.uid, row.username, "登录", "后台管理账号+密码登录成功", request.client.host)
  145. row.login_date = datetime.now()
  146. row.login_ip = request.client.host
  147. # row.login = row.login + 1
  148. db.commit()
  149. access_token_expires = timedelta(seconds = 7200)
  150. access_token = security.create_access_token(
  151. data={"sub": user_id}, expires_delta = access_token_expires
  152. )
  153. refresh_token_expires = timedelta(seconds = 7200)
  154. refresh_token = security.create_access_token(
  155. data={"sub": user_id}, expires_delta = refresh_token_expires
  156. )
  157. return {
  158. "code": 200,
  159. "msg": "操作成功",
  160. "data": {
  161. "access_token": access_token,
  162. "refresh_token": refresh_token,
  163. "expire_in": 7200,
  164. "refresh_expire_in": 7200,
  165. "client_id": clientId,
  166. "scope": "",
  167. "openid": ""
  168. }
  169. }
  170. @router.post('/logout')
  171. async def logout(
  172. request: Request,
  173. db: Session = Depends(get_db),
  174. client_id: str = Depends(valid_access_token)
  175. ):
  176. return {
  177. "code": 200,
  178. "msg": "退出成功"
  179. }
  180. @router.post('/yzy/callback')
  181. async def yzy(
  182. request: Request,
  183. db: Session = Depends(get_db),
  184. data: dict = Depends(remove_xss_json)
  185. ):
  186. code = data['code']
  187. state = data['state']
  188. state_str = base64.b64decode(state).decode('utf-8')
  189. state_json = json.loads(state_str)
  190. print(code, state_json)
  191. if code != 'xxxxx':
  192. resp = YzyApi.get_user_info(code)
  193. if resp['errcode'] != 0:
  194. return {
  195. "code": 500,
  196. "msg": "Code异常"
  197. }
  198. user_id = resp['UserId']
  199. else:
  200. user_id = "eb4kehgy6wj4qn0jhx1dk6"
  201. row = db.query(YzyOrgUserEntity).filter(YzyOrgUserEntity.userid == user_id).first()
  202. if row is None:
  203. return {
  204. "code": 500,
  205. "msg": "user_id异常"
  206. }
  207. yzy_account = row.account
  208. row = db.query(SysUser).filter(SysUser.yzy_account == yzy_account).first()
  209. if row is None:
  210. return {
  211. "code": 500,
  212. "msg": "用户不是本系统用户"
  213. }
  214. user_id = str(row.user_id)
  215. access_token_expires = timedelta(seconds = 7200)
  216. access_token = security.create_access_token(
  217. data={"sub": user_id}, expires_delta = access_token_expires
  218. )
  219. refresh_token_expires = timedelta(seconds = 7200)
  220. refresh_token = security.create_access_token(
  221. data={"sub": user_id}, expires_delta = refresh_token_expires
  222. )
  223. return {
  224. "code": 200,
  225. "msg": "粤政易登录成功",
  226. "data": {
  227. "access_token": access_token,
  228. "refresh_token": refresh_token,
  229. "expire_in": 7200,
  230. "refresh_expire_in": 7200,
  231. "scope": "",
  232. "redirect_url": state_json['redirect_url']
  233. }
  234. }