auth.py 5.9 KB

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