def disconnect(self): try: is_chap = self.settings.config.portal.chap in (1, '1', 'chap') userIp = self.current_user.ipaddr nas = self.get_nas(self.current_user.nasaddr) ac_addr = nas['ip_addr'] ac_port = int(nas['ac_port']) secret = utils.safestr(nas['bas_secret']) _vendor = utils.safestr(nas['portal_vendor']) if _vendor not in ('cmccv1', 'cmccv2', 'huaweiv1', 'huaweiv2'): defer.returnValue('not support vendor %s' % _vendor) send_portal = functools.partial(client.send, secret, log=self.syslog, debug=self.settings.config.debug, vendor=_vendor) vendor = client.PortalClient.vendors.get(_vendor) logout_req = vendor.proto.newReqLogout(userIp, secret, chap=is_chap) logout_resp = yield send_portal(data=logout_req, host=ac_addr, port=ac_port) if logout_resp.errCode > 0: _err_msg = u'{0},{1}'.format( vendor.mod.AckLogoutErrs[logout_resp.errCode], utils.safeunicode(logout_resp.get_text_info()[0] or '')) logger.error(_err_msg) defer.returnValue('disconnect done!') except Exception as err: defer.returnValue(err)
def send_sms(self, phone, tplid, args = [], kwargs = {}): smspwd = md5(utils.safestr('%s%s' % (self.apiuser, self.apikey))).hexdigest() _params = dict(ac='send', uid=utils.safestr(apikey), pwd=smspwd, mobile=utils.safestr(phone), content=utils.safestr(json.dumps(kwargs, ensure_ascii=False))) sms_api_url = '%s?%s' % (self.url, urlencode(_params)) resp = yield httpclient.fetch(sms_api_url, followRedirect=True) if '200' != str(resp.status_code): defer.returnValue(True) else: ret = json.loads(resp.body) if self.debug: logger.info(ret) defer.returnValue(ret['stat'] == 0)
def post(self): try: if os.environ.get('DEMO_VER'): self.write(u'这是一个演示版本,不提供此功能') return file_path = os.path.join(os.path.dirname(taurusxradius.__file__), 'static/dnsv') try: if not os.path.exists(file_path): os.makedirs(file_path) except: pass f = self.request.files['Filedata'][0] filename = os.path.basename(utils.safestr(f['filename'])) save_path = os.path.join(file_path, filename) tf = open(save_path, 'wb') filestr = f['body'] tf.write(filestr.strip()) tf.close() logger.info('write {0}'.format(save_path)) self.write(u'上传完成') except Exception as err: logger.error(err) self.write(u'上传失败 %s' % utils.safeunicode(err))
def post(self): try: pic_path = os.path.join(os.path.dirname(taurusxradius.__file__), 'static/pics') try: if not os.path.exists(pic_path): os.makedirs(pic_path) except: pass f = self.request.files['Filedata'][0] filename = os.path.basename(utils.safestr(f['filename'])) savename = 'pic{0}_{1}'.format(tools.gen_num_id(13), filename) save_path = os.path.join(pic_path, savename) tf = open(save_path, 'wb') tf.write(f['body']) tf.close() if not safefile.isimg(save_path): os.remove(save_path) logger.error('error upload file %s' % save_path) self.write(u'上传的文件不是图片类型') return logger.info('write {0}'.format(save_path)) self.write(u'upload ok') except Exception as err: logger.error(err) self.write(u'上传失败 %s' % utils.safeunicode(err))
def event_sms_account_expire(self, account_number): userinfo = self.get_customer_info(account_number) tplid = self.get_tpl_id(ExpireNotify) if not tplid: return args = [ utils.safestr(userinfo.realname), account_number, utils.safestr(userinfo.product_name), userinfo.expire_date ] kwargs = {} kwargs['customer'] = utils.safestr(userinfo.realname) kwargs['username'] = account_number kwargs['product'] = utils.safestr(userinfo.product_name) kwargs['expire'] = userinfo.expire_date dispatch.pub(EVENT_SENDSMS, userinfo.mobile, tplid, args=args, kwargs=kwargs)
def make_message(self, param): param_keys = list(param.keys()) param_keys.sort() param_str = '' for key in param_keys: param_str += key + u'=' + utils.safeunicode(param[key]) + u'&' param_str = param_str[:-1] sign_str = self.apikey + u'&' + param_str + u'&' + self.apikey param['signature'] = md5(utils.safestr(sign_str)).hexdigest() return param
def get_error_html(self, status_code=500, **kwargs): logger.info('http error : [status_code:{0}], {1}'.format( status_code, utils.safestr(kwargs))) if status_code == 404: return self.render_string('error.html', msg=u'404:页面不存在') elif status_code == 403: return self.render_string('error.html', msg=u'403:非法的请求') elif status_code == 500: return self.render_string('error.html', msg=u'500:服务器处理失败,请联系管理员') else: return self.render_string('error.html', msg=u'%s:服务器处理失败,请联系管理员' % status_code)
def get_menu_data(self, mps_apiurl): try: _fetch_result = lambda: self.wechat.get_menu().get('menu') menus_obj = self.cache.aget(self.MpsMenuCacheKey, _fetch_result, expire=86400) if isinstance(menus_obj, (str, unicode)): menus_obj = json.loads(menus_obj) logger.debug(menus_obj) return menus_obj except Exception as err: logger.exception(err) mstr = menutpl_str.replace('{mps_apiurl}', mps_apiurl) return json.loads(utils.safestr(mstr))
def render_string(self, template_name, **template_vars): template_vars['xsrf_form_html'] = self.xsrf_form_html template_vars['current_user'] = self.current_user template_vars['login_time'] = self.get_secure_cookie( 'portal_logintime') template_vars['request'] = self.request template_vars['requri'] = '{0}://{1}'.format(self.request.protocol, self.request.host) template_vars['handler'] = self template_vars['utils'] = utils try: mytemplate = self.tp_lookup.get_template('wlanportal/%s' % template_name) return mytemplate.render(**template_vars) except Exception as err: logger.info('Render template error {0}'.format(utils.safestr(err))) raise
def radius_process(resp=None, resp_attrs={}): try: if not resp_attrs: return resp attrs = resp_attrs.get('attrs', {}) for attr_name, attr_value in attrs.iteritems(): try: resp.AddAttribute(utils.safestr(attr_name), attr_value) except: errmsg = u'add radius attr error %s:%s, %s' % ( attr_name, attr_value, traceback.format_exc()) logger.error(errmsg, trace='radius', tag='radius_attrs_process_error') return resp except Exception as err: logger.exception(err, trace='radius', tag='radius_attrs_process_error') return resp
def check_data(self, formdata): """ 用户开户数据校验 """ max_giftdays = self.db.query( models.TrProductAttr.attr_value).filter_by( product_id=formdata.product_id, attr_name='max_giftdays').scalar() or 0 if int(max_giftdays) < int(formdata.get('giftdays', 0)): self.last_error = u'最大赠送天数不能超过%s天' % max_giftdays return False max_giftflows = self.db.query( models.TrProductAttr.attr_value).filter_by( product_id=formdata.product_id, attr_name='max_giftflows').scalar() or 0 if float(max_giftflows) < float(formdata.get('giftflows', 0)): self.last_error = u'最大赠送流量不能超过%sG' % max_giftflows return False node = self.db.query(models.TrNode).get(formdata.node_id) if not node: self.last_error = u'区域节点不存在' return False account_count = self.db.query(models.TrAccount).filter_by( account_number=formdata.account_number).count() if account_count > 0: self.last_error = u'账号%s已经存在' % formdata.account_number return False _ip_address = formdata.get('ip_address') if _ip_address and self.db.query(models.TrAccount).filter_by( ip_address=_ip_address).count() > 0: self.last_error = u'ip%s已经被使用' % utils.safestr(_ip_address) return False if self.db.query(models.TrCustomer).filter_by( customer_name=formdata.account_number).count() > 0: if account_count == 0: self.db.query(models.TrCustomer).filter_by( customer_name=formdata.account_number).delete() else: self.last_error = u'用户名%s已经存在' % formdata.account_number return False return True
def send(self, **kwargs): try: _ctime = self.tz.localize(datetime.datetime.now()) ttl = kwargs.pop('ttl', '7d') reqmsg = dict(ver=__version__, timestamp=_ctime.isoformat(), tag=kwargs.pop('tag', 'normal')) reqmsg.update(kwargs) puturl = '{0}/{1}/taurusxr?ttl={2}'.format(self.apiurl, self.index, ttl) user_and_pwd = '{0}:{1}'.format(self.apiuser, self.apipwd) headers = { 'Authorization': ['Basic {0}'.format(base64.b64encode(user_and_pwd))] } postdata = utils.safestr(json.dumps(reqmsg, ensure_ascii=False)) d = httpclient.fetch(puturl, postdata=postdata, headers=headers) d.addCallback(lambda r: logger.debug(r.body)).addErrback( lambda e: sys.stderr.write(repr(e))) except: traceback.print_exc()
def send_sms(self, phone, tplid, args = [], kwargs = {}): if self.debug: logger.info('send sms to phone %s' % phone) params = {'%{0}%'.format(k):v for k, v in kwargs.iteritems()} param = self.make_message({'smsUser': self.apiuser, 'templateId': tplid, 'msgType': 0, 'phone': phone, 'vars': utils.safestr(json.dumps(params, ensure_ascii=False))}) if self.debug: logger.info(param) resp = yield httpclient.fetch(SmsApi.url, postdata=urlencode(param)) ret = json.loads(resp.body) if self.debug: logger.info(ret) if ret['statusCode'] == 200: defer.returnValue(True) else: _err = 'Send sms failure, statusCode=%s,message=%s' % (ret['statusCode'], utils.safestr(ret['message'])) logger.error(_err, trace='event') defer.returnValue(False)
class PortalListen(protocol.DatagramProtocol): def __init__(self, config, dbengine=None, **kwargs): self.dbengine = dbengine self.config = config self.mcache = redis_cache.CacheManager(redis_conf(config), cache_name='Portald') self.actions = {huawei.NTF_LOGOUT: self.doAckNtfLogout} reactor.callLater(3.0, self.init_task) def get_nas(self, ip_addr): def fetch_result(): table = models.TrwBas.__table__ with self.db_engine.begin() as conn: return conn.execute( table.select().where(table.c.ip_addr == ip_addr)).first() return self.mcache.aget(settings.wlanportal_cache_key(ip_addr), fetch_result, expire=600) def init_task(self): _task = task.LoopingCall(self.send_ntf_heart) _task.start(self.config.portal.ntf_heart) def send_ntf_heart(self): pass def doAckNtfLogout(self, req, vendor, secret, (host, port)): try: resp = vendor.proto.newMessage(vendor.ACK_NTF_LOGOUT, req.userIp, req.serialNo, req.reqId, str(secret)) logger.info('Send portal packet to %s:%s: %s' % (host, port, utils.safestr(req))) self.transport.write(str(resp), (host, port)) except Exception as err: logger.exception(err)
try: resp = vendor.proto.newMessage(vendor.ACK_NTF_LOGOUT, req.userIp, req.serialNo, req.reqId, str(secret)) logger.info('Send portal packet to %s:%s: %s' % (host, port, utils.safestr(req))) self.transport.write(str(resp), (host, port)) except Exception as err: logger.exception(err) def datagramReceived(self, datagram, (host, port)): try: nas = self.get_nas(host) ac_addr = nas['ip_addr'] ac_port = int(nas['ac_port']) secret = utils.safestr(nas['bas_secret']) _vendor = utils.safestr(nas['portal_vendor']) if _vendor not in ('cmccv1', 'cmccv2', 'huaweiv1', 'huaweiv2'): self.render_error( msg=u'AC server portal_vendor {0} not support '.format( _vendor)) return vendor = client.PortalClient.vendors.get(_vendor) req = vendor.proto(secret=secret, packet=datagram, source=(host, port)) logger.info('Received portal packet from %s:%s: %s' % (host, port, utils.safestr(req))) if req.type in self.actions: self.actions[req.type](req, vendor, secret, (host, port)) else:
def post(self, pid): try: openid = self.session.get('mps_openid', os.environ.get('DEV_OPEN_ID')) realname = self.get_argument('realname', '').strip() node_id = self.get_argument('node_id', '').strip() mobile = self.get_argument('mobile', '').strip() address = self.get_argument('address', '').strip() idcard = self.get_argument('idcard', '').strip() username = self.get_argument('username', '').strip() password = self.get_argument('password', '').strip() months = int(self.get_argument('months', '1')) days = int(self.get_argument('days', '1')) wechat_bind = int(self.get_argument('wechat_bind', '0')) product = self.db.query(models.TrProduct).filter_by(id=pid).first() if not product: return self.render('error.html', msg=u'资费不存在') if not realname: return self.render('wxorder_form.html', product=product, msg=u'姓名不能为空', **self.get_params()) if not rules.is_alphanum2(6, 16).valid(utils.safestr(username)): return self.render('wxorder_form.html', product=product, msg=u'用户名校验错误,必须是长度为6-16位的英文字符数字', **self.get_params()) if not rules.is_alphanum2(6, 16).valid(password): return self.render('wxorder_form.html', product=product, msg=u'密码校验错误,必须是6-16为的英文字符数字', **self.get_params()) if wechat_bind == 1 and self.db.query(models.TrCustomer).filter_by( wechat_oid=openid).count() > 0: return self.render('wxorder_form.html', product=product, msg=u'微信账号已绑定', **self.get_params()) fee_value, expire_date = self.calc_fee(product.id, months=months, charge_fee=utils.fen2yuan( product.fee_price)) order_id = tools.gen_num_id(16) formdata = Storage({'order_attach': 'neworder'}) formdata['wxpay_body'] = u'套餐订购:%s' % product.product_name formdata['openid'] = openid formdata['order_id'] = order_id formdata['node_id'] = node_id formdata['area_id'] = '' formdata['realname'] = realname formdata['idcard'] = idcard formdata['mobile'] = mobile formdata['address'] = address formdata['account_number'] = username formdata['password'] = password formdata['ip_address'] = '' formdata['product_id'] = product.id formdata['agency_id'] = '' formdata['charge_code'] = '' formdata['months'] = months formdata['days'] = days formdata['giftdays'] = 0 formdata['giftflows'] = 0 formdata['fee_value'] = fee_value formdata['expire_date'] = expire_date formdata['status'] = 1 formdata['builder_name'] = '' formdata['customer_desc'] = u'客户微信自助开户' formdata['billing_type'] = 1 formdata['accept_source'] = 'wechat' if wechat_bind == 1: formdata['wechat_oid'] = openid self.paycache.set(order_wxpaycaache_key(order_id), formdata, 28800) self.redirect('/mps/wxorder/pay/%s' % order_id) except Exception as err: logger.exception(err, trace='wechat') self.render('error.html', msg=u'套餐订购失败,请联系客服 %s' % repr(err))
def post(self, **kwargs): qstr = self.get_argument('qstr', '') username = self.get_argument('username', None) password = self.get_argument('password', None) if 'qstr' in kwargs: qstr = kwargs['qstr'] if 'username' in kwargs: username = kwargs['username'] if 'password' in kwargs: password = kwargs['password'] wlan_params = self.get_wlan_params(qstr) logger.info(u'post wlan params:{0}'.format( utils.safeunicode(wlan_params))) ssid = wlan_params.get('ssid', 'default') wlanacip = wlan_params.get('wlanacip', '127.0.0.1') nasid = wlan_params.get('nasid', 'default') wlanuserip = wlan_params.get('wlanuserip', self.request.remote_ip) is_chap = self.settings.config.portal.chap in (1, '1', 'chap') userIp = wlanuserip start_time = time.time() nas = self.get_nas(wlanacip, nasid=nasid) if not nas: self.render_error( msg=u'AC设备地址或ID {0},{1} 未在本系统注册 '.format(wlanacip, nasid)) return else: ac_addr = nas['ip_addr'] ac_port = int(nas['ac_port']) secret = utils.safestr(nas['bas_secret']) _vendor = utils.safestr(nas['portal_vendor']) if _vendor not in ('cmccv1', 'cmccv2', 'huaweiv1', 'huaweiv2'): logger.error(nas) self.render_error( msg=u'AC设备 portal_vendor {0} 不支持 '.format(_vendor)) return hm_mac = wlan_params.get('wlanstamac', '').replace('.', ':').replace('-', ':') macbstr = hm_mac and struct.pack( 'BBBBBB', *[int(i, base=16) for i in hm_mac.split(':')]) or None send_portal = functools.partial(client.send, secret, log=logger, debug=self.settings.debug, vendor=_vendor, timeout=5) vendor = client.PortalClient.vendors.get(_vendor) if self.settings.debug: logger.info(u'开始 [username:%s] Portal认证, 参数:%s' % (username, utils.safeunicode(wlan_params))) tpl = self.get_template_attrs(ssid) firsturl = tpl.get('home_page', '/navigate') def back_login(msg=u''): self.render(self.get_login_template(tpl['tpl_path']), tpl=tpl, msg=msg, qstr=qstr, **wlan_params) if not username: back_login(msg=u'用户名不能为空') return try: challenge_resp = None if is_chap: challenge_req = vendor.proto.newReqChallenge(userIp, secret, mac=macbstr, chap=is_chap) challenge_resp = yield send_portal(data=challenge_req, host=ac_addr, port=ac_port) if challenge_resp.errCode > 0: if challenge_resp.errCode == 2: self.set_remerber_user(username, password) self.redirect(firsturl) return raise Exception(vendor.mod.AckChallengeErrs[ challenge_resp.errCode]) if challenge_resp: auth_req = vendor.proto.newReqAuth( userIp, username, password, challenge_resp.reqId, challenge_resp.get_challenge(), secret, ac_addr, serialNo=challenge_req.serialNo, mac=macbstr, chap=is_chap) else: auth_req = vendor.proto.newReqAuth(userIp, username, password, 0, None, secret, ac_addr, chap=is_chap) auth_resp = yield send_portal(data=auth_req, host=ac_addr, port=ac_port) if auth_resp.errCode > 0: if auth_resp.errCode == 2: self.set_remerber_user(username, password) self.redirect(firsturl) return text_info = auth_resp.get_text_info() _err_msg = u'{0},{1}'.format( vendor.mod.AckAuthErrs[auth_resp.errCode], utils.safeunicode(text_info and text_info[0] or '')) raise Exception(_err_msg) affack_req = vendor.proto.newAffAckAuth(userIp, secret, ac_addr, auth_req.serialNo, auth_resp.reqId, mac=macbstr, chap=is_chap) send_portal(data=affack_req, host=ac_addr, port=ac_port, noresp=True) logger.info(u'用户 [username:{0}] 认证成功'.format(username)) if self.settings.debug: logger.debug(u'用户 [username:%s] 认证耗时 [cast:%s ms]' % (username, (time.time() - start_time) * 1000)) self.set_remerber_user(username, password) self.redirect(firsturl) except Exception as err: import traceback traceback.print_exc() back_login(msg=u'用户认证失败,%s' % utils.safeunicode(err.message)) return