auth.py 10 KB

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