mirror of https://github.com/tp4a/teleport
temp.
parent
852aba747a
commit
9ad28a298c
|
@ -106,6 +106,7 @@ class WebServerCore:
|
|||
# settings['compiled_template_cache'] = False
|
||||
# settings['static_hash_cache'] = False
|
||||
|
||||
|
||||
from eom_app.controller import controllers
|
||||
web_app = tornado.web.Application(controllers, **settings)
|
||||
|
||||
|
@ -117,5 +118,9 @@ class WebServerCore:
|
|||
log.e('Can not listen on port {}, maybe it been used by another application.\n'.format(cfg.server_port))
|
||||
return 0
|
||||
|
||||
# 启动session超时管理
|
||||
web_session().start()
|
||||
tornado.ioloop.IOLoop.instance().start()
|
||||
web_session().stop()
|
||||
|
||||
return 0
|
||||
|
|
|
@ -1,44 +1,91 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pickle
|
||||
# import pickle
|
||||
import time
|
||||
import datetime
|
||||
import threading
|
||||
|
||||
from pymemcache.client.base import Client as mem_client
|
||||
# from pymemcache.client.base import Client as mem_client
|
||||
from .configs import app_cfg
|
||||
from eom_common.eomcore.logger import log
|
||||
|
||||
cfg = app_cfg()
|
||||
|
||||
SESSION_EXPIRE = 3600 # 60*60
|
||||
SESSION_EXPIRE = 3600 # 60*60 默认超时时间为1小时
|
||||
|
||||
# TODO: session接口需要支持超时(超时的session应该移除,避免内存占用越来越大)
|
||||
# SESSION_EXPIRE = 1800 # 30*60
|
||||
# SESSION_EXPIRE = 30
|
||||
|
||||
class WebSession:
|
||||
class WebSession(threading.Thread):
|
||||
"""
|
||||
:type _mem_client: pymemcache.client.base.Client
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(name='session-manager-thread')
|
||||
|
||||
import builtins
|
||||
if '__web_session__' in builtins.__dict__:
|
||||
raise RuntimeError('WebSession object exists, you can not create more than one instance.')
|
||||
|
||||
# session表,session_id为索引,每个项为一个字典,包括 v(Value), t(Timestamp when add or modify), e(Expire seconds)
|
||||
self._session_dict = dict()
|
||||
|
||||
self._lock = threading.RLock()
|
||||
self._stop_flag = False
|
||||
|
||||
def init(self):
|
||||
return True
|
||||
|
||||
def add(self, s_id, value):
|
||||
self._session_dict[s_id] = value
|
||||
def stop(self):
|
||||
self._stop_flag = True
|
||||
self.join()
|
||||
log.v('{} stopped.'.format(self.name))
|
||||
|
||||
def set(self, s_id, value):
|
||||
self._session_dict[s_id] = value
|
||||
def run(self):
|
||||
while True:
|
||||
_now = int(datetime.datetime.utcnow().timestamp())
|
||||
with self._lock:
|
||||
_keys = [k for k in self._session_dict]
|
||||
for k in _keys:
|
||||
if self._session_dict[k]['e'] == 0:
|
||||
continue
|
||||
if _now - self._session_dict[k]['t'] > self._session_dict[k]['e']:
|
||||
del self._session_dict[k]
|
||||
|
||||
# 每隔一分钟检查一次超时的会话
|
||||
for i in range(60):
|
||||
if not self._stop_flag:
|
||||
time.sleep(1)
|
||||
|
||||
def set(self, s_id, value, expire=SESSION_EXPIRE):
|
||||
"""
|
||||
设置一个会话数据,如果expire为负数,则立即删除已经存在的名为s_id的会话,如果expire为0,则此会话数据永不过期。expire的单位为秒。
|
||||
@param s_id: string
|
||||
@param value: string
|
||||
@param expire: integer
|
||||
@return: None
|
||||
"""
|
||||
if expire < 0:
|
||||
with self._lock:
|
||||
if s_id in self._session_dict:
|
||||
del self._session_dict[s_id]
|
||||
else:
|
||||
self._session_dict[s_id] = {'v': value, 't': int(datetime.datetime.utcnow().timestamp()), 'e': expire}
|
||||
|
||||
def get(self, s_id, _default=None):
|
||||
if s_id in self._session_dict:
|
||||
v = self._session_dict[s_id]
|
||||
else:
|
||||
v = _default
|
||||
return v
|
||||
with self._lock:
|
||||
if s_id in self._session_dict:
|
||||
if self._session_dict[s_id]['e'] == 0:
|
||||
return self._session_dict[s_id]['v']
|
||||
else:
|
||||
if int(datetime.datetime.utcnow().timestamp()) - self._session_dict[s_id]['t'] > self._session_dict[s_id]['e']:
|
||||
del self._session_dict[s_id]
|
||||
return _default
|
||||
else:
|
||||
self._session_dict[s_id]['t'] = int(datetime.datetime.utcnow().timestamp())
|
||||
return self._session_dict[s_id]['v']
|
||||
|
||||
else:
|
||||
return _default
|
||||
|
||||
|
||||
def web_session():
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import random
|
||||
import io
|
||||
|
||||
import json
|
||||
import urllib.parse
|
||||
import tornado.gen
|
||||
import tornado.httpclient
|
||||
|
||||
from wheezy.captcha.image import background
|
||||
from wheezy.captcha.image import captcha
|
||||
from wheezy.captcha.image import curve
|
||||
from wheezy.captcha.image import noise
|
||||
from wheezy.captcha.image import offset
|
||||
from wheezy.captcha.image import rotate
|
||||
from wheezy.captcha.image import smooth
|
||||
from wheezy.captcha.image import text
|
||||
from wheezy.captcha.image import warp
|
||||
|
||||
from .configs import app_cfg
|
||||
|
||||
cfg = app_cfg()
|
||||
|
@ -27,3 +41,38 @@ def async_post_http(url, values):
|
|||
except:
|
||||
# return {'code': -2, 'message': 'can not fetch {}'.format(url)}
|
||||
return None
|
||||
|
||||
|
||||
_chars = 'ACDEFHJKLMNPQRTVWXY34679'
|
||||
|
||||
|
||||
def gen_captcha():
|
||||
_font_dir = os.path.join(cfg.res_path, 'fonts')
|
||||
captcha_image_t = captcha(
|
||||
width=136,
|
||||
height=36,
|
||||
drawings=[
|
||||
background(color='#eeeeee'),
|
||||
text(fonts=[
|
||||
os.path.join(_font_dir, '001.ttf')
|
||||
],
|
||||
font_sizes=(28, 34, 36, 32),
|
||||
color='#63a8f5',
|
||||
squeeze_factor=1.1,
|
||||
drawings=[
|
||||
warp(dx_factor=0.05, dy_factor=0.05),
|
||||
rotate(angle=15),
|
||||
offset()
|
||||
]),
|
||||
curve(color='#af6fff', width=2, number=9),
|
||||
noise(),
|
||||
smooth()
|
||||
])
|
||||
|
||||
chars_t = random.sample(_chars, 4)
|
||||
image = captcha_image_t(chars_t)
|
||||
|
||||
out = io.BytesIO()
|
||||
image.save(out, "jpeg", quality=90)
|
||||
# web.header('Content-Type','image/jpeg')
|
||||
return ''.join(chars_t), out.getvalue()
|
||||
|
|
|
@ -2,19 +2,25 @@
|
|||
|
||||
import json
|
||||
import random
|
||||
from random import Random
|
||||
# from random import Random
|
||||
|
||||
from eom_app.module import user
|
||||
from eom_common.eomcore.logger import *
|
||||
from .base import SwxAppHandler, SwxJsonpHandler, SwxAuthJsonHandler
|
||||
from .helper.captcha import gen_captcha
|
||||
from eom_app.app.util import gen_captcha
|
||||
|
||||
|
||||
class LoginHandler(SwxAppHandler):
|
||||
def get(self):
|
||||
ref = self.get_argument('ref', '/')
|
||||
|
||||
self.render('auth/login.mako', reference=ref, captcha_random=random.random())
|
||||
user = self.get_current_user()
|
||||
if user['id'] == 0:
|
||||
user_name = ''
|
||||
else:
|
||||
user_name = user['name']
|
||||
|
||||
self.render('auth/login.mako', user_name=user_name, reference=ref, captcha_random=random.random())
|
||||
|
||||
|
||||
class VerifyUser(SwxJsonpHandler):
|
||||
|
@ -235,7 +241,6 @@ class ModifyPwd(SwxAuthJsonHandler):
|
|||
log.e('can not set session.')
|
||||
self.write_json(-1)
|
||||
|
||||
|
||||
#
|
||||
# class GetEncData(SwxAuthJsonHandler):
|
||||
# def post(self):
|
||||
|
|
|
@ -10,7 +10,7 @@ import mako.template
|
|||
import tornado.web
|
||||
from tornado.escape import json_encode
|
||||
|
||||
from eom_app.app.session import web_session
|
||||
from eom_app.app.session import web_session, SESSION_EXPIRE
|
||||
from eom_app.app.configs import app_cfg
|
||||
from eom_app.app.const import *
|
||||
|
||||
|
@ -22,8 +22,7 @@ class SwxBaseHandler(tornado.web.RequestHandler):
|
|||
super().__init__(application, request, **kwargs)
|
||||
|
||||
self._s_id = None
|
||||
self._s_val = dict()
|
||||
# self.lookup = None
|
||||
# self._s_val = dict()
|
||||
|
||||
def initialize(self):
|
||||
template_path = self.get_template_path()
|
||||
|
@ -46,32 +45,22 @@ class SwxBaseHandler(tornado.web.RequestHandler):
|
|||
|
||||
self._s_id = self.get_cookie('_sid')
|
||||
if self._s_id is None:
|
||||
self._s_id = 'ywl_{}_{}'.format(int(time.time()), binascii.b2a_hex(os.urandom(8)).decode())
|
||||
self._s_id = 'tp_{}_{}'.format(int(time.time()), binascii.b2a_hex(os.urandom(8)).decode())
|
||||
self.set_cookie('_sid', self._s_id)
|
||||
web_session().add(self._s_id, self._s_val)
|
||||
else:
|
||||
# print('sid:', self._s_id)
|
||||
self._s_val = web_session().get(self._s_id)
|
||||
if self._s_val is None:
|
||||
self._s_val = dict()
|
||||
web_session().add(self._s_id, self._s_val)
|
||||
|
||||
def set_session(self, name, value):
|
||||
self._s_val[name] = value
|
||||
web_session().set(self._s_id, self._s_val)
|
||||
def set_session(self, name, value, expire=SESSION_EXPIRE):
|
||||
k = '{}-{}'.format(self._s_id, name)
|
||||
web_session().set(k, value, expire)
|
||||
|
||||
def get_session(self, name, default=None):
|
||||
if name in self._s_val:
|
||||
return self._s_val[name]
|
||||
else:
|
||||
return default
|
||||
def get_session(self, name, _default=None):
|
||||
k = '{}-{}'.format(self._s_id, name)
|
||||
return web_session().get(k, _default)
|
||||
|
||||
def del_session(self, name):
|
||||
if name in self._s_val:
|
||||
del self._s_val[name]
|
||||
k = '{}-{}'.format(self._s_id, name)
|
||||
return web_session().set(k, '', -1)
|
||||
|
||||
def get_current_user(self):
|
||||
# return self.get_secure_cookie('user')
|
||||
user = self.get_session('user')
|
||||
if user is None:
|
||||
user = dict()
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import random
|
||||
from io import BytesIO, StringIO
|
||||
from os import path
|
||||
|
||||
from eom_app.app.configs import app_cfg
|
||||
from wheezy.captcha.image import background
|
||||
from wheezy.captcha.image import captcha
|
||||
from wheezy.captcha.image import curve
|
||||
from wheezy.captcha.image import noise
|
||||
from wheezy.captcha.image import offset
|
||||
from wheezy.captcha.image import rotate
|
||||
from wheezy.captcha.image import smooth
|
||||
from wheezy.captcha.image import text
|
||||
from wheezy.captcha.image import warp
|
||||
|
||||
|
||||
cfg = app_cfg()
|
||||
_chars = 'ACDEFHJKLMNPQRTVWXY34679'
|
||||
|
||||
|
||||
def gen_captcha():
|
||||
_font_dir = path.join(cfg.res_path, 'fonts')
|
||||
captcha_image_t = captcha(
|
||||
width=136,
|
||||
height=36,
|
||||
drawings=[
|
||||
background(color='#eeeeee'),
|
||||
text(fonts=[
|
||||
path.join(_font_dir, '001.ttf')
|
||||
],
|
||||
font_sizes=(28, 34, 36, 32),
|
||||
color='#63a8f5',
|
||||
squeeze_factor=1.1,
|
||||
drawings=[
|
||||
warp(dx_factor=0.05, dy_factor=0.05),
|
||||
rotate(angle=15),
|
||||
offset()
|
||||
]),
|
||||
curve(color='#af6fff', width=2, number=9),
|
||||
noise(),
|
||||
smooth()
|
||||
])
|
||||
|
||||
chars_t = random.sample(_chars, 4)
|
||||
image = captcha_image_t(chars_t)
|
||||
|
||||
out = BytesIO()
|
||||
image.save(out, "jpeg", quality=90)
|
||||
# web.header('Content-Type','image/jpeg')
|
||||
return ''.join(chars_t), out.getvalue()
|
||||
|
|
@ -15,10 +15,12 @@ from eom_app.app.util import *
|
|||
from eom_app.module import host
|
||||
from eom_app.module.common import *
|
||||
from eom_common.eomcore.logger import *
|
||||
from .base import SwxAuthHandler, SwxAuthJsonHandler
|
||||
from .base import SwxAuthHandler, SwxAuthJsonHandler, SwxAdminJsonHandler
|
||||
|
||||
cfg = app_cfg()
|
||||
|
||||
# 临时认证ID的基数,每次使用时均递减
|
||||
tmp_auth_id_base = -1
|
||||
|
||||
class IndexHandler(SwxAuthHandler):
|
||||
def get(self):
|
||||
|
@ -46,7 +48,7 @@ class IndexHandler(SwxAuthHandler):
|
|||
ts_server['telnet_port'] = cfg.core.telnet.port
|
||||
|
||||
# f.write("\"use strict\";\nvar teleport_ip = \"{}\";\n".format(ts_server['ip']))
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
return self.write(-1)
|
||||
# finally:
|
||||
# f.close()
|
||||
|
@ -773,44 +775,6 @@ class UpdateHostExtendInfo(SwxAuthJsonHandler):
|
|||
self.write_json(-1)
|
||||
|
||||
|
||||
# @tornado.gen.coroutine
|
||||
# def post_http(url, values):
|
||||
# try:
|
||||
# # log.v('post_http(), url={}\n'.format(url))
|
||||
#
|
||||
# # user_agent = 'Mozilla/4.0 (compatible;MSIE 5.5; Windows NT)'
|
||||
# # values = {
|
||||
# # 'act': 'login',
|
||||
# # 'login[email]': 'yzhang@i9i8.com',
|
||||
# # 'login[password]': '123456'
|
||||
# # }
|
||||
# values = json.dumps(values)
|
||||
# data = urllib.parse.quote(values).encode('utf-8')
|
||||
# # headers = {'User-Agent': user_agent}
|
||||
#
|
||||
# # req = urllib.request.Request(url=url, data=data, headers=headers)
|
||||
# # response = urllib.request.urlopen(req, timeout=3)
|
||||
#
|
||||
# client = tornado.httpclient.AsyncHTTPClient()
|
||||
# r = yield client.fetch(url, body=data, method='POST')
|
||||
# print('----------', r.body)
|
||||
# return r.body
|
||||
#
|
||||
#
|
||||
# # the_page = response.read()
|
||||
# # info = response.info()
|
||||
# # _zip = info.get('Content-Encoding')
|
||||
# # if _zip == 'gzip':
|
||||
# # the_page = gzip.decompress(the_page)
|
||||
# # else:
|
||||
# # pass
|
||||
# # the_page = the_page.decode()
|
||||
# # # print(the_page)
|
||||
# # return the_page
|
||||
# except:
|
||||
# return None
|
||||
|
||||
|
||||
class GetSessionId(SwxAuthJsonHandler):
|
||||
@tornado.gen.coroutine
|
||||
def post(self, *args, **kwargs):
|
||||
|
@ -840,24 +804,11 @@ class GetSessionId(SwxAuthJsonHandler):
|
|||
|
||||
url = 'http://{}:{}/rpc'.format(ts_server_rpc_ip, ts_server_rpc_port)
|
||||
req = {'method': 'request_session', 'param': {'authid': auth_id}}
|
||||
|
||||
# values = json.dumps(req)
|
||||
# data = urllib.parse.quote(values).encode('utf-8')
|
||||
# client = tornado.httpclient.AsyncHTTPClient()
|
||||
# r = yield client.fetch(url, body=data, method='POST')
|
||||
# if r.code == 200:
|
||||
# # self.write(r.body)
|
||||
# print('+++++++++', r.body)
|
||||
|
||||
_yr = async_post_http(url, req)
|
||||
return_data = yield _yr
|
||||
if return_data is None:
|
||||
return self.write_json(-1)
|
||||
|
||||
# return_data = result.decode()
|
||||
# print('############', return_data)
|
||||
# return_data = json.loads(result.decode())
|
||||
|
||||
if 'code' not in return_data:
|
||||
return self.write_json(-1)
|
||||
|
||||
|
@ -941,7 +892,7 @@ class AdminGetSessionId(SwxAuthJsonHandler):
|
|||
return self.write_json(0, data=data)
|
||||
|
||||
|
||||
class AdminFastGetSessionId(SwxAuthJsonHandler):
|
||||
class AdminFastGetSessionId(SwxAdminJsonHandler):
|
||||
def post(self, *args, **kwargs):
|
||||
args = self.get_argument('args', None)
|
||||
if args is not None:
|
||||
|
@ -1001,17 +952,23 @@ class AdminFastGetSessionId(SwxAuthJsonHandler):
|
|||
|
||||
values['account'] = 'admin'
|
||||
|
||||
# config_list = host.get_config_list()
|
||||
# ts_server_rpc_ip = '127.0.0.1'
|
||||
#
|
||||
# if 'ts_server_rpc_ip' in config_list:
|
||||
# ts_server_rpc_ip = config_list['ts_server_rpc_ip']
|
||||
# ts_server_rpc_port = 52080
|
||||
# if 'ts_server_rpc_port' in config_list:
|
||||
# ts_server_rpc_port = config_list['ts_server_rpc_port']
|
||||
ts_server_rpc_ip = cfg.core.rpc.ip
|
||||
ts_server_rpc_port = cfg.core.rpc.port
|
||||
|
||||
# 为统一调用形式,这里先将密码或私钥传递给core服务加密,然后生成一个临时认证信息供后续request_session时core服务来获取
|
||||
url = 'http://{}:{}/rpc'.format(ts_server_rpc_ip, ts_server_rpc_port)
|
||||
req = {'method': 'enc', 'param': {'p': values['uauth']}}
|
||||
_yr = async_post_http(url, req)
|
||||
return_data = yield _yr
|
||||
if return_data is None:
|
||||
return self.write_json(-1)
|
||||
if 'code' not in return_data or return_data['code'] != 0:
|
||||
return self.write_json(-1)
|
||||
|
||||
values['uauth'] = return_data['data']['c']
|
||||
|
||||
# TODO: 生成一个临时认证信息备用(如何保证临时的auth_id唯一?)
|
||||
|
||||
url = 'http://{}:{}/request_session'.format(ts_server_rpc_ip, ts_server_rpc_port)
|
||||
# values['auth_id'] = auth_id
|
||||
return_data = post_http(url, values)
|
||||
|
|
|
@ -53,8 +53,7 @@
|
|||
<div class="inputbox">
|
||||
<div class="input-group input-group-lg">
|
||||
<span class="input-group-addon"><i class="fa fa-user fa-fw"></i></span>
|
||||
<input id="username_account" type="text" class="form-control" placeholder="账号:邮箱地址或手机号"
|
||||
data-toggle="popover" data-trigger="manual" data-placement="top">
|
||||
<input id="username_account" type="text" class="form-control" placeholder="账号:邮箱地址或手机号" data-toggle="popover" data-trigger="manual" data-placement="top" value="${ user_name }">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue