dever 6 years ago
parent
commit
4efd360df3
6 changed files with 157 additions and 103 deletions
  1. 20 4
      admin/page/site.py
  2. 9 3
      cron.py
  3. 55 54
      front/api/main.py
  4. 14 0
      model/signature.py
  5. 4 2
      model/site.py
  6. 55 40
      service/convert.py

+ 20 - 4
admin/page/site.py

@@ -16,8 +16,8 @@ class site_path(Load):
 			,width = '600'
 			,height = '600'
 			,search = (('label-1','workdate-time-start','workdate-time-end','name-input-mlike'), (u'日期范围',u'开始时间',u'截止时间',u'站点名称'))
-			,thead = (u'站点key', u'站点名称', u'快捷功能', u'站点token', u'更新时间')
-			,tbody = ('key','name','func', 'token', 'cdate')
+			,thead = (u'站点名称', u'appid', u'appsecret', u'快捷功能', u'更新时间')
+			,tbody = ('name','appid', 'appsecret', 'func', 'cdate')
 			,state = True
 		)
 		menu = (
@@ -40,19 +40,34 @@ class site_update_path(Load):
 	def get(self):
 		self.set(
 			path = '/site/site'
-			,label = (u'站点名称',u'站点网址',u'通知接口',u'站点key',u'站点token',u'浏览页数')
-			,update = ('name-input-required','link-input-required','api-input-required','key-input-required','token-input-required','page-input-required')
+			,label = (u'站点名称',u'站点网址',u'通知接口',u'限制页数',u'开始时间', u'结束时间')
+			,update = ('name-input-required','link-input-required','api-input-required','page-input-required','sdate-date-required','edate-date-required')
 		)
 		self.one('site')
 		self.show('update')
 	@Web.auth
 	@Web.setting
 	def post(self):
+		id = self.input('id')
+		if not id:
+			self.getAppId()
 		self.update('site')
 	@Web.auth
 	@Web.setting
 	def delete(self):
 		self.drop('site')
+	@Web.auth
+	@Web.setting
+	def getAppId(self):
+		self.data['update']['appid'] = Demeter.compressUuid(Demeter.uuid())
+		self.data['update']['appsecret'] = Demeter.hash()
+
+		model = Demeter.model('site')
+		model.appid = self.data['update']['appid']
+		model.appsecret = self.data['update']['appsecret']
+		info = model.select(type='fetchone')
+		if info:
+			self.getAppId()
 
 class convert_path(Load):
 	@Web.auth
@@ -118,6 +133,7 @@ class convert_update_path(Load):
 		info = self.service('convert').getFile(site['key'], self.data['update']['file'])
 		self.data['update']['uid'] = -1
 		self.data['update']['file_id'] = -1
+		self.data['update']['file_type'] = 2
 		self.data['update']['name'] = info['name']
 		self.data['update']['key'] = info['key']
 		self.data['update']['ext'] = info['ext']

+ 9 - 3
cron.py

@@ -1,10 +1,8 @@
 # -*- coding: utf-8 -*-
 import time
 from demeter.core import *
-'''
 from gevent import monkey; monkey.patch_socket()
 import gevent
-'''
 timeSleep = 15
 
 def command(file):
@@ -25,7 +23,15 @@ def convert():
 			time.sleep(timeSleep)
 			i = 0
 
+# 清理一天前的sign
+def signature():
+	service = Demeter.service('convert')
+	service.crearSignature()
+
 def handle():
-	convert()
+	gevent.joinall([
+		gevent.spawn(convert),
+		gevent.spawn(signature),
+	])
 
 handle()

+ 55 - 54
front/api/main.py

@@ -8,38 +8,71 @@ from .__load__ import *
 
 class Common(object):
 	@staticmethod
-	def signature(self):
-		key = self.input('key')
+	def signature(self, status):
+		appid = self.input('appid')
+		timestamp = self.input('timestamp')
 		nonce = self.input('nonce')
 		signature = self.input('signature')
 		file = self.input('file')
+		file_id = self.input('file_id')
 		uid = self.input('uid')
 
-		if not key:
-			self.out('参数错误:key')
+		if not appid:
+			self.out('参数错误:appid')
+		if not timestamp:
+			self.out('参数错误:timestamp')
 		if not nonce:
 			self.out('参数错误:nonce')
 		if not signature:
 			self.out('参数错误:signature')
 		if not file:
 			self.out('参数错误:file')
+		if not file_id:
+			self.out('参数错误:file_id')
 		if not uid:
 			self.out('参数错误:uid')
 
 		site = Demeter.model('site')
-		site.key = key
+		site.appid = appid
 
 		self.data['site'] = site.select(type='fetchone')
 
 		if not self.data['site']:
 			self.out('站点信息不存在')
 
-		key = key + '&' + self.data['site']['token'] + '&' + nonce + '&' + file + '&' + uid
-		key = Demeter.sha1(key)
-		if key != signature:
+		time = Demeter.time()
+		if time < self.data['site']['sdate'] or time > self.data['site']['edate']:
+			self.out('授权已失效')
+
+		self.service = Demeter.service('convert')
+
+		self.referer = self.request.headers['referer']
+		self.host = Demeter.host(self.data['site']['link'])
+
+		if not self.referer:
+			self.out('验证失败')
+
+		if self.host != Demeter.host(self.referer):
 			self.out('验证失败')
 
-		return key
+
+		self.param = self.service.signature(self.data['site']['id'], appid, self.data['site']['appsecret'], timestamp, nonce, file, file_id, uid)
+
+		if not self.param:
+			self.out('验证失败')
+
+		if self.param['signature'] != signature:
+			self.out('验证失败')
+
+		if status == 1:
+			file = self.service.update(self.data['site']['id'], self.data['site']['appid'], file, file_id, file_type, uid)
+		else:
+			file = self.service.get(self.data['site']['id'], self.data['site']['appid'], file);
+
+		if not file:
+			self.out('未生成文件信息')
+
+		return file
 
 class test_path(Load):
 	@Web.setting
@@ -116,7 +149,7 @@ class test_path(Load):
 
 
 # 请求转换 /main/convert 接口必须后端获取,token不允许暴露
-#http://192.168.33.10:8088/main/convert?signature=44e3cd684a9fe697792a235c8c57838211f5823a&key=mo1209&nonce=1529659172&file=http%3A%2F%2F192.168.33.10%2Fsystem%2Fdata%2Fupload%2Fdoc_con%2F5b2cbf1064fd8.doc&uid=1
+#http://192.168.33.10:8088/main/convert?signature=44e3cd684a9fe697792a235c8c57838211f5823a&appid=mo1209&nonce=1529659172&file=http%3A%2F%2F192.168.33.10%2Fsystem%2Fdata%2Fupload%2Fdoc_con%2F5b2cbf1064fd8.doc&uid=1
 class convert_path(Load):
 	@Web.setting
 	def get(self):
@@ -134,13 +167,7 @@ class convert_path(Load):
 
 		uid = self.input('uid')
 		self.data = {}
-		Common.signature(self)
-
-		service = Demeter.service('convert')
-		file = service.update(self.data['site']['id'], self.data['site']['key'], file, file_id, file_type, uid)
-
-		if not file:
-			self.out('未生成文件信息')
+		file = Common.signature(self, 1)
 
 		# 推入到redis队列
 		if file['status'] == 1 and update == 'insert':
@@ -153,7 +180,6 @@ class convert_path(Load):
 		url = self.request.protocol + "://" + self.request.host
 
 		self.data['file'] = {
-			#'id' : file['id'],
 			'status' : file['status'],
 			'url' : url + file['url'],
 			'ext' : file['ext'],
@@ -170,13 +196,7 @@ class get_path(Load):
 
 		file = self.input('file')
 		self.data = {}
-		Common.signature(self)
-
-		service = Demeter.service('convert')
-		file = service.get(self.data['site']['id'], self.data['site']['key'], file);
-
-		if not file:
-			self.out('未生成文件信息')
+		file = Common.signature(self, 2)
 
 		del self.data['site']['token']
 
@@ -203,16 +223,10 @@ class auth_path(Load):
 		file = self.input('file')
 		uid = self.input('uid')
 		self.data = {}
-		Common.signature(self)
-
-		service = Demeter.service('convert')
-		file = service.get(self.data['site']['id'], self.data['site']['key'], file);
-
-		if not file:
-			self.out('未生成文件信息')
+		file = Common.signature(self, 2)
 
 		if file:
-			service.auth(self.data['site']['id'], uid, file['id'], 2)
+			self.service.auth(self.data['site']['id'], uid, file['id'], 2)
 
 		self.out('yes', {'msg':1})
 
@@ -222,23 +236,16 @@ class view_path(Load):
 	def get(self):
 		import re
 
-		key = self.input('key')
+		appid = self.input('appid')
 		nonce = self.input('nonce')
 		signature = self.input('signature')
 		file = self.input('file')
 		uid = self.input('uid')
 		page = self.input('page')
 		path = self.input('path')
-		host = self.input('host')
 
 		self.data = {}
-		Common.signature(self)
-
-		service = Demeter.service('convert')
-		file = service.get(self.data['site']['id'], self.data['site']['key'], file);
-
-		if not file:
-			self.out('未生成文件信息')
+		file = Common.signature(self, 2)
 
 		if page:
 			url = self.request.protocol + "://" + self.request.host
@@ -247,7 +254,7 @@ class view_path(Load):
 			content = File.readContent(page)
 			content = content.replace('src="', 'src="' + str(static))
 		else:
-			user = service.getAuth(self.data['site']['id'], uid, file['id'])
+			user = self.service.getAuth(self.data['site']['id'], uid, file['id'])
 
 			limit = -1
 			if not user and file['file_type'] == 1:
@@ -270,11 +277,11 @@ class view_path(Load):
 					content = re.sub(pattern, '', content)
 
 				path = path.replace(Demeter.path + 'runtime', '')
-				url = url + '/main/view?path=' + str(path) + '&file=' + file['key'] + '&nonce=' + nonce + '&key=' + key + '&signature=' + signature + '&uid=' + uid + '&page='
+				url = url + '/main/view?path=' + str(path) + '&file=' + file['key'] + '&nonce=' + nonce + '&appid=' + appid + '&signature=' + signature + '&uid=' + uid + '&page='
 				content = content.replace('data-page-url="', 'data-page-url="' + url)
 
 				script = '<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>'
-				script = script + '<script>document.domain="'+host+'";$(function(){var e = pdf2htmlEX.defaultViewer;var page = e.pages.length;var original_height = 0;var height = e.container.clientHeight;for(var i in e.pages){height = height + e.pages[i].original_height;original_height = e.pages[i].original_height;};parent.setHeight(height, original_height, page)})</script>'
+				script = script + '<script>document.domain="'+self.host+'";$(function(){var e = pdf2htmlEX.defaultViewer;var page = e.pages.length;var original_height = 0;var height = e.container.clientHeight;for(var i in e.pages){height = height + e.pages[i].original_height;original_height = e.pages[i].original_height;};parent.setHeight(height, original_height, page)})</script>'
 				content = content.replace('</body>', script + '</body>')
 
 				style = '<style>#page-container{background-color: white;background-image: none;}#sidebar{background-color: white;background-image: none;}.pf{border:1px solid #bababa;box-shadow:none}</style>'
@@ -287,22 +294,16 @@ class view_path(Load):
 class down_path(Load):
 	@Web.setting
 	def get(self):
-		key = self.input('key')
+		appid = self.input('appid')
 		nonce = self.input('nonce')
 		signature = self.input('signature')
 		file = self.input('file')
 		uid = self.input('uid')
 
 		self.data = {}
-		Common.signature(self)
-
-		service = Demeter.service('convert')
-		file = service.get(self.data['site']['id'], self.data['site']['key'], file);
-
-		if not file:
-			self.out('未生成文件信息')
+		file = Common.signature(self, 2)
 
-		user = service.getAuth(self.data['site']['id'], uid, file['id'])
+		user = self.service.getAuth(self.data['site']['id'], uid, file['id'])
 
 		if not user and file['file_type'] == 1:
 			# 没有文件信息,则不允许下载

+ 14 - 0
model/signature.py

@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+"""
+    demeter database
+    name:signature.py
+"""
+from .__load__ import *
+
+class Signature(Model):
+	__table__ = 'signature'
+	__comment__ = 'signature记录表'
+	id = Fields(type='int', primaryKey=True, autoIncrement=True, comment='ID')
+	site_id = Fields(type='int', comment='所属站点')
+	signature = Fields(type='varchar(500)', comment='signature')
+	cdate = Fields(type='int', default='time', comment='创建时间')

+ 4 - 2
model/site.py

@@ -11,9 +11,11 @@ class Site(Model):
 	id = Fields(type='int', primaryKey=True, autoIncrement=True, comment='站点ID')
 	name = Fields(type='varchar(50)', comment='站点名')
 	link = Fields(type='varchar(200)', comment='站点网址')
-	key = Fields(type='varchar(30)', comment='站点key')
-	token = Fields(type='varchar(300)', comment='授权token')
+	appid = Fields(type='varchar(150)', comment='appid')
+	appsecret = Fields(type='varchar(300)', comment='appsecret')
 	page = Fields(type='int', comment='默认显示多少页')
+	sdate = Fields(type='int', comment='开始时间')
+	edate = Fields(type='int', comment='结束时间')
 	api = Fields(type='varchar(300)', comment='通知接口')
 	state = Fields(type='boolean', default='True', comment='数据存在状态')
 	cdate = Fields(type='int', default='time', comment='创建时间')

+ 55 - 40
service/convert.py

@@ -3,22 +3,47 @@ from .__load__ import *
 
 class Convert(object):
 
-	def getKey(self, site_key, file):
-		return Demeter.sha1(str(site_key) + '_' + file)
+	def crearSignature():
+		num = Demeter.time() - 3600*24
+		model = Demeter.model('signature')
+		model.cdate.assign(num, exp='<=')
+		model.delete()
+
+	def signature(self, site_id, appid, appsecret, timestamp, nonce, file, file_id, uid):
+		sign = Demeter.sha1(appid + '&' + appsecret + '&' + str(timestamp) + '&' + str(nonce) + '&' + file + '&' + str(file_id) + '&' + str(uid));
+
+		time = Demeter.time()
+		num = 3600*12
+		if time - timestamp > num:
+			return False
+
+		# sign 只能使用一次
+		model = Demeter.model('signature')
+		model.signature = sign
+		model.site_id = site_id
+		info = model.select(type='fetchone')
+		if info:
+			return False
 
-	def get(self, site, site_key, file):
-		convert = Demeter.model('convert')
-		convert.site_id = site
-		#convert.key = self.getKey(site_key, file)
-		convert.key = file
+		param = {}
+		param['signature'] = sign
+		param['appid'] = appid
+		param['appsecret'] = appsecret
+		param['timestamp'] = timestamp
+		param['nonce'] = nonce
+		param['file'] = file
+		param['file_id'] = file_id
+		param['uid'] = uid
 
-		data = convert.select(type='fetchone')
+		model.signature = sign
+		model.site_id = site_id
+		model.insert()
 
-		return data
+		return param
 
-	def update(self, site, site_key, file, file_id, file_type, uid):
+	def update(self, site, appid, file, file_id, file_type, uid):
 
-		info = self.getFile(site_key, file)
+		info = self.getFile(appid, file)
 
 		convert = Demeter.model('convert')
 		convert.site_id = site
@@ -90,29 +115,29 @@ class Convert(object):
 		return True
 
 
-	def getFile(self, site_key, file):
+	def getFile(self, appid, file):
 		info = {}
 
 		(filepath,temp) = os.path.split(file)
 		(filename,extension) = os.path.splitext(temp)
 
 		info['file'] = file
-		info['key'] = self.getKey(site_key, file)
+		info['key'] = self.getKey(appid, file)
 		info['ext'] = extension
 		info['name'] = filename
 
-		info = self.getLocalFile(site_key, file, info)
+		info = self.getLocalFile(appid, file, info)
 
 		return info
 
-	def getLocalFile(self, site_key, file, info):
+	def getLocalFile(self, appid, file, info):
 
 		day = str(date.today())
 		day = day.split('-')
 
 		#filename =  Demeter.md5(str(uuid.uuid5(uuid.uuid1(), info['key'])))
 		filename =  info['key']
-		filepath = str(site_key) + '/' + day[0] + '/' + day[1] + '/' + day[2]
+		filepath = str(appid) + '/' + day[0] + '/' + day[1] + '/' + day[2]
 		filepath = File.mkdirs(os.path.join(Demeter.path, 'runtime','files', filepath)) + '/' + filename
 
 		local = filepath + info['ext']
@@ -229,32 +254,22 @@ class Convert(object):
 	def api(self, info, site):
 		if 'file_id' in info and info['file_id']:
 			api = site['api']
-			key = site['key']
-			token = site['token']
+
+			appid = site['appid']
+			appsecret = site['appsecret']
+			timestamp = Demeter.time()
+			nonce = Demeter.nonce()
 			file = info['key']
 			file_id = info['file_id']
 			uid = info['uid']
-			file_size = info['file_size']
-
-			url = 'main/view'
-			page = info['page']
-			ext = info['ext']
-
-			nonce = Demeter.time()
-			sign = Demeter.sha1(key + '&' + token + '&' + str(nonce) + '&' + file + '&' + str(uid));
-
-			param = {}
-			param['signature'] = sign
-			param['key'] = key
-			param['nonce'] = nonce
-			param['file'] = file
-			param['file_id'] = file_id
-			param['uid'] = uid
-			param['url'] = url
-			param['img'] = img
-			param['page'] = page
-			param['ext'] = ext
-			param['file_size'] = file_size
+
+			param = self.signature(site['id'], appid, appsecret, timestamp, nonce, file, file_id, uid)
+
+			param['url'] = 'main/view'
+			param['img'] = info['html'] + '.jpg'
+			param['page'] = info['page']
+			param['ext'] = info['ext']
+			param['file_size'] = info['file_size']
 
 			Demeter.curl(api, param, 'post')
 
@@ -270,7 +285,7 @@ class Convert(object):
 				req_image.append(img_page.make_blob('jpg'))
 			i = i+1
 
-		dest = info['html'].replace('/files/', '/upload/')
+		dest = info['html']
 		for img in req_image:
 			ff = open(dest + '.jpg','wb')
 			ff.write(img)