关于Centos的Redis 安装:
上一章我们结束了测试号的申请,也在公众平台页面控制台熟悉了一些重要的数据,接下来就是项目的编写。我个人很随意,用的编写环境是Win10,测试环境是自己租的阿里云服务器,Centos7,基本配置都已搞定,包括Python3 以及所需包,Redis数据库等。下面就简单说一下项目是实现哪些功能:
1、 接口验证,这是自己编写后台必要的环节;
2、回复功能,包括对客户发送的语音,文字的回复,关注事件回复;
3、自定义菜单功能,并对点击菜单的事件进行响应;
4、网页授权,这个是为了跳转自定义页面实现业务逻辑功能,因为我们必须进行验证拿到用户的唯一标识openid;
5、调用微信公众平台的接口实现开放功能,比如扫码,分享等等,当然本次项目我只实现airkiss智能配网,因为我是搞硬件的。
一、下面是整个项目的文件以及简易流程图:
二、下图是工程目录
三、文件简单描述
1、wxconfig.py 是我们存放基本配置信息的文件,包括AppId,AppSecret,一些自定义菜单所属url等等。
2、wxmenu.py 是我们自定义菜单的文件,它可以独立运行,仅需要运行一次即可,在菜单变动的时候我们可以选择手动执行,当然也可以放在一些文件中,让它定时执行或者触发执行,在本次工程中我让它在项目运行的时候执行一次。
3、wxcache.py 是基于redis的access_token和jsapi_ticket缓存控制文件,因为微信接口需要的access_token和jsapi_ticket会过期,需要定时刷新,并且获取它们的接口有调用次数限制,因此必须严格控制它们的存在,保证所有模块调用它们不会产生冲突。
4、wxtoken.py 是控制access_token和jsapi_ticket更新文件,就是中枢服务器。
5、wxreply.py 是处理客户行为数据的文件,包括对菜单的响应和留言的回复。
6、wxauthorize.py 是对用户请求自定义页面的拦截,主要是为了拿到用户的openid,所设的关卡,拿到之后进行放行。
7、wxsign.py 是对js-sdk接口调用前的签名,没有这个步骤是没办法进行调用微信开放功能的。
8、wxlogger.py 是日志模块 负责监控程序的运行状态
9、wxhandler.py 是路由指向的类所在模块,包括三个路由 配置和回复路由、页面请求路由和签名请求路由。
10、main.py 是程序的入口文件,对token的定时任务初始化 自定义菜单的创建 端口绑定以及路由声明等等。
11、html文件时页面文件
12、server.* 是https ssl证书文件,可以不使用签名证书 用http服务器也是可以的
四、上完整代码:
1、main.py
import sys
sys.path.append("./handler")
# 将 handler 目录下的文件放到和main.py同级的目录
import tornado.ioloop
import tornado.web
from tornado import httpserver
import time
from wxtoken import WxShedule # 维护 token 更新模块
from wxmenu import WxMenuServer # 自定义菜单模块
from wxhandler import pageHandler,wxStartHandler,getSignHandler # 路由模块
def main():
application = tornado.web.Application([
(r'/start', wxStartHandler), # 验证配置接口和消息回复路由
(r'/sign',getSignHandler), # 获取js-sdk签名路由
(r'/page(.*)', pageHandler), # 请求微信自定义web页面
],
autoreload=False,
debug=False
)
#application.listen(9000) #http服务器开启
# 下面代码是配置https服务器,当然选用http服务器也是可以的
server = httpserver.HTTPServer(application, ssl_options={
"certfile":"server.crt",
"keyfile": "server.key",
}
)
# 执行定时任务,定时刷新获取 access_token和jsapi_ticket
wx_shedule = WxShedule()
wx_shedule.excute()
# 给点时间去获取token
time.sleep(3)
# 初始化一次菜单
wx_menu_server = WxMenuServer()
wx_menu_server.create_menu()
server.listen(9000)# 单进程开启
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
2、wxtoken.py
import tornado.ioloop
import requests
import json
from wxconfig import WxConfig
from wxcache import TokenCache
from wxlogger import logger
class WxShedule(object):
"""负责access_token和jsapi_ticket的更新"""
_token_cache = TokenCache() # 微信token缓存实例
_expire_time_access_token = 7000 * 1000 # token过期时间
def excute(self):
"""执行定时器任务"""
# IOLoop.instance().call_later(delay, callback, *args, **kwargs)
# 延时delay秒之后,将callback加入到tornado的加入到的处理队列里面,异步调用只调用一次
tornado.ioloop.IOLoop.instance().call_later(0, self.get_access_token)
# tornado.ioloop.PeriodicCallback(callback, callback_time, io_loop=None)
# callback设定定时调用的方法 callback_time设定每次调用之间的间隔,单位毫秒
tornado.ioloop.PeriodicCallback(self.get_access_token, self._expire_time_access_token).start()
def get_access_token(self):
"""获取微信全局唯一票据access_token"""
try:
url = WxConfig.get_access_token_url
r = requests.get(url)
if r.status_code == 200:
d = json.loads(r.text)
if 'access_token' in d.keys():
access_token = d['access_token']
# 添加至redis中
self._token_cache.set_access_cache('access_token', access_token)
# 获取JS_SDK权限签名的jsapi_ticket
self.get_jsapi_ticket()
else:
errcode = d['errcode']
# 出现错误10s之后调用一次,获取access_token
tornado.ioloop.IOLoop.instance().call_later(10, self.get_access_token)
else:
# 网络错误10s之后调用一次,获取access_token
tornado.ioloop.IOLoop.instance().call_later(10, self.get_access_token)
except Exception as e:
logger.error('wxtoken get_access_token'+str(e))
def get_jsapi_ticket(self):
"""获取JS_SDK权限签名的jsapi_ticket"""
try:
# 从redis中获取access_token
access_token = self._token_cache.get_cache('access_token')
if access_token:
url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi' % access_token
r = requests.get(url)
if r.status_code == 200:
d = json.loads(r.text)
errcode = d['errcode']
if errcode == 0:
jsapi_ticket = d['ticket']
# 添加至redis中
self._token_cache.set_js_cache('jsapi_ticket', jsapi_ticket)
else:
tornado.ioloop.IOLoop.instance().call_later(10, self.get_jsapi_ticket)
else:
# 网络错误 重新获取
tornado.ioloop.IOLoop.instance().call_later(10, self.get_jsapi_ticket)
else:
# access_token已经过期 重新获取
tornado.ioloop.IOLoop.instance().call_later(10, self.get_access_token)
except Exception as e:
logger.error('wxtoken get_jsapi_ticket'+str(e))
3、wxsign.py
import time
import random
import string
import hashlib
from wxcache import TokenCache
from wxlogger import logger
def get_js_sdk_sign(url):
"""获取调用js-sdk必要的数据 nonceStr timestamp signature"""
try:
_token_cache = TokenCache() # 微信token缓存实例
jsapi_ticket = _token_cache.get_cache('jsapi_ticket') # 从redis中提取jsapi_ticket
if jsapi_ticket:
nonceStr=''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
timestamp=int(time.time())
url=url
ret = {
'nonceStr': nonceStr,
'jsapi_ticket': jsapi_ticket,
'timestamp': timestamp,
'url': url
}
_string = '&'.join(['%s=%s' % (key.lower(), ret[key]) for key in sorted(ret)])
ret['signature'] = hashlib.sha1(_string.encode('utf-8')).hexdigest()
return ret
except Exception as e:
logger.error('wxsign get_js_sdk_sign'+str(e))
4、wxreply.py
from wxlogger import logger
"""这是一个处理客户发送信息的文件"""
def reply_text(FromUserName, ToUserName, CreateTime, Content):
"""回复文本消息模板"""
textTpl = """<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content></xml>"""
out = textTpl % (FromUserName, ToUserName, CreateTime, 'text', Content)
return out
def receive_msg(msg):
# 这是一个将疑问改成成熟句子的函数,例如:你好吗 公众号回复:你好
if msg[-1] == u'吗':
return msg[:len(msg)-1]
elif len(msg)>2 and msg[-2] == u'吗' :
return msg[:len(msg)-2]
else:
return "你说的话我好像不明白?"
def receive_event(event,key):
# 如果是关注公众号事件
if event == 'subscribe':
return "感谢关注!"
# 如果是点击菜单拉取消息事件
elif event == 'CLICK':
# 接下来就是根据你点击不同的菜单拉去不同的消息啦
# 我为了省事,不进行判断啦,如果需要判断请根据 key进行判断
return "你点击了菜单"+key
# 如果是点击菜单跳转Url事件,不做任何处理因为微信客户端会自行处理
elif event == 'VIEW':
return None
5、wxmenu.py
from wxconfig import WxConfig
from wxcache import TokenCache
from wxauthorize import WxAuthorServer
from wxlogger import logger
import requests
import json
class WxMenuServer(object):
"""这是一个创建自定义菜单的文件,当你需要更新菜单的时候执行这个文件"""
token_cache = TokenCache() # 微信token缓存对象
# 微信网页授权server,目的是为了重定向,类似关卡
wx_author_server = WxAuthorServer()
def create_menu(self):
"""
自定义菜单创建接口,这个非常灵活,
我们可以设置权限,可以传入参数等等,
我们这边就直接写死了
"""
try:
access_token=self.token_cache.get_cache('access_token')
if not access_token:
logger.error('创建菜单 获取 token失败')
return None
url = WxConfig.menu_create_url + access_token
data = self.create_menu_data()
r = requests.post(url, data.encode('utf-8'))
if not r.status_code == 200:
logger.error('创建菜单 网络错误')
return None
json_res = json.loads(r.text)
if 'errcode' in json_res.keys():
errcode = json_res['errcode']
return errcode
except Exception as e:
logger.error('wxmenu create_menu'+str(e))
def get_menu(self):
"""自定义菜单查询接口"""
try:
access_token=self.token_cache.get_cache('access_token')
if not access_token:
return None
url = WxConfig.menu_get_url + access_token
r = requests.get(url)
if not r.status_code == 200:
return None
json_res = json.loads(r.text)
if 'errcode' in json_res.keys():
errcode = json_res['errcode']
logger.error('自定义菜单查询失败!')
return errcode
except Exception as e:
logger.error('wxmenu get_menu'+str(e))
def delete_menu(self):
"""自定义菜单删除接口"""
try:
access_token=self.token_cache.get_cache('access_token')
if not access_token:
return None
url = WxConfig.menu_delete_url + access_token
r = requests.get(url)
if not r.status_code == 200:
return None
json_res = json.loads(r.text)
if 'errcode' in json_res.keys():
errcode = json_res['errcode']
logger.error('自定义菜单删除失败')
return errcode
except Exception as e:
logger.error('wxmenu delete_menu'+str(e))
def create_menu_data(self):
"""创建菜单数据"""
menu_data = {'button': []} # 大菜单
menu_Index0 = {
'type': 'click',
'name': '一级菜单',
"key": "menu1"
}
menu_data['button'].append(menu_Index0)
menu_Index1 = {
"name": "二级菜单",
"sub_button":
[
{
"type": "view",
"name": "test",
"url": self.wx_author_server.get_code_url('test')
},
{
"type": "click",
"name": "click",
"key": "click"
}
]
}
menu_data['button'].append(menu_Index1)
# 菜单三 我们让它请求页面,验证js-sdk权限
menu_Index2 = {
'type': 'view',
'name': 'airkiss',
"url": self.wx_author_server.get_code_url('airkiss')
}
menu_data['button'].append(menu_Index2)
menu_data = json.dumps(menu_data, ensure_ascii=False)
return menu_data
if __name__ == '__main__':
wx_menu_server = WxMenuServer()
wx_menu_server.create_menu()
6、wxlogger.py
import logging
from logging import Logger
log_path = './out.log'
error_path = './error.log'
'''日志管理类 负责开发过程中的数据的追踪'''
def init_logger(logger_name):
if logger_name not in Logger.manager.loggerDict:
# 创建一个logger
logger = logging.getLogger(logger_name)
logger.setLevel(logging.INFO) # 设置最低级别
# 定义handler的输出格式
df = '%Y-%m-%d %H:%M:%S'
format_str = '[%(asctime)s]: %(name)s %(levelname)s %(lineno)s %(message)s'
formatter = logging.Formatter(format_str, df)
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler(log_path,encoding = 'utf-8') # 指定utf-8格式编码,避免输出的日志文本乱码
fh.setLevel(logging.INFO)
fh.setFormatter(formatter)
# 创建一个handler,用于将日志输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(formatter)
# 给logger添加handler
logger.addHandler(fh)
logger.addHandler(ch)
# 创建一个handler,用于写入错误日志文件
efh = logging.FileHandler(error_path,encoding = 'utf-8') # 指定utf-8格式编码,避免输出的日志文本乱码
efh.setLevel(logging.ERROR)
efh.setFormatter(formatter)
# 创建一个handler,用于将错误日志输出到控制台
ech = logging.StreamHandler()
ech.setLevel(logging.ERROR)
ech.setFormatter(formatter)
# 给logger添加handler
logger.addHandler(efh)
logger.addHandler(ech)
logger = logging.getLogger(logger_name)
return logger
logger = init_logger('wx_run_log')
7、wxhandler.py
import tornado.web
# 这是python 标准库 用来处理 xml文件的
import xml.etree.ElementTree as ET
import hashlib
import time
# wxreply文件是我写关于处理回复的函数,我们导出来必要的函数
from wxreply import receive_msg,receive_event,reply_text
from wxconfig import WxConfig
from wxcache import TokenCache
from wxauthorize import WxAuthorServer
from wxlogger import logger
from wxsign import get_js_sdk_sign
class wxStartHandler(tornado.web.RequestHandler):
"""
微信服务器签名验证和消息回复
check_signature: 校验signature是否正确
"""
def check_signature(self, signature, timestamp, nonce):
"""校验token是否正确"""
# 这个是token 和我们在微信公众平台配置接口填写一致
token = 'iotbird'
L = [timestamp, nonce, token]
L.sort()
s = L[0] + L[1] + L[2]
sha1 = hashlib.sha1(s.encode('utf-8')).hexdigest()
# 对于验证结果返回true or false
return sha1 == signature
#
def get(self):
"""这是get请求,处理配置接口验证的"""
try:
# 获取参数
signature = self.get_argument('signature')
timestamp = self.get_argument('timestamp')
nonce = self.get_argument('nonce')
echostr = self.get_argument('echostr')
# 调用验证函数
result = self.check_signature(signature, timestamp, nonce)
if result:
self.write(echostr)
else:
logger.error('微信sign校验,---校验失败')
except Exception as e:
logger.error('wxhandler get'+str(e))
def post(self):
""" 这是post请求 接收消息,获取参数 """
body = self.request.body
# 返回的bodys是xml格式,通过ET转换为键值对格式,方便提取信息
data = ET.fromstring(body)
ToUserName = data.find('ToUserName').text
FromUserName = data.find('FromUserName').text
MsgType = data.find('MsgType').text
# 如果发送的是消息请求,判断是文字还是语音,因为我们取发送的内容位置不一样
if MsgType == 'text' or MsgType == 'voice':
try:
MsgId = data.find("MsgId").text
if MsgType == 'text':
Content = data.find('Content').text # 文本消息内容
elif MsgType == 'voice':
Content = data.find('Recognition').text # 语音识别结果,UTF8编码
# 调用回复函数判断接受的信息,然后返回对应的内容
reply_content=receive_msg(Content)
CreateTime = int(time.time())
# 调用回复信息封装函数,要指定用户,时间和回复内容
out = reply_text(FromUserName, ToUserName, CreateTime, reply_content)
self.write(out)
except Exception as e:
logger.error('wxStartHandler post'+str(e))
# 如果接收的是事件,我们也要处理
elif MsgType == 'event':
try:
Event = data.find('Event').text
Event_key = data.find('EventKey').text
CreateTime = int(time.time())
# 判断事件,并返回内容
reply_content = receive_event(Event,Event_key)
if reply_content:
out = reply_text(FromUserName, ToUserName, CreateTime, reply_content)
self.write(out)
except Exception as e:
logger.error('wxStartHandler post'+str(e))
class pageHandler(tornado.web.RequestHandler):
'''页面跳转控制路由'''
wx_config = WxConfig()
'''微信网页授权server'''
wx_author_server = WxAuthorServer()
def get(self, flag):
try:
if flag == '/wxauthor':
'''微信网页授权'''
code = self.get_argument('code')
state = self.get_argument('state')
# 获取重定向的url
redirect_url = self.wx_config.wx_menu_state_map[state]
if code:
# 通过code换取网页授权access_token
data = self.wx_author_server.get_auth_access_token(code)
openid = data['openid']
if openid:
# 跳到自己的业务界面
self.redirect(redirect_url)
else:
# 获取不到openid
logger.error('获取不到openid')
# 如果请求的是airkiss页面
elif flag == '/airkiss':
self.render('../page/airkiss.html')
elif flag == '/test':
self.render('../page/test.html')
except Exception as e:
logger.error('pageHandler post'+str(e))
class getSignHandler(tornado.web.RequestHandler):
"""返回js-sdk签名数据"""
wx_config = WxConfig()
wx_token_cache = TokenCache()
def get(self):
# 调用微信js-sdk接口功能 需要签名
sign=get_js_sdk_sign('%s/wx/page/airkiss'% self.wx_config.AppHost)
sign['appId']=self.wx_config.AppID
self.write(sign)
8、wxconfig.py
class WxConfig(object):
"""微信开发--基础配置"""
# 测试账号
AppID = 'wxxxxxxxxxx'
AppSecret = '6xxxxxxxxxxxxxxxxxxx'
"""微信网页开发域名"""
AppHost = 'https://www.f203.online'
'''获取access_token接口'''
get_access_token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s' % (AppID, AppSecret)
'''自定义菜单创建接口'''
menu_create_url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token='
'''自定义菜单查询接口'''
menu_get_url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token='
'''自定义菜单删除接口'''
menu_delete_url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token='
'''微信公众号菜单映射页面,参数是page/后面的'''
wx_menu_state_map = {
'airkiss': '%s/wx/page/airkiss'% AppHost,
'test': '%s/wx/page/test'% AppHost
}
9、wxcache.py
# 缓存 access_token 和 jsapi_ticket,并且即使更新,防止过期
# access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。
# 开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时
# jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取
# 我们用redis去存数据,并设置过期时间
import redis
from wxlogger import logger
class BaseCache(object):
"""缓存类父类"""
_host = '127.0.0.1'
_port = 6379
_database = 0
_password = ''
@property
def redis_ctl(self):
"""redis控制句柄,就是连接对象"""
redis_ctl = redis.Redis(host=self._host, port=self._port, db=self._database, password=self._password)
return redis_ctl
class TokenCache(BaseCache):
"""微信token缓存"""
_expire_access_token = 7200 # 微信access_token过期时间, 2小时
_expire_js_token = 7200 # 微信jsapi_ticket, 过期时间, 7200秒
def set_access_cache(self, key, value):
"""添加微信access_token验证相关redis"""
self.redis_ctl.set(key, value)
# 设置过期时间
self.redis_ctl.expire(key, self._expire_access_token)
logger.info('更新了 access_token')
def set_js_cache(self, key, value):
"""添加网页授权相关redis"""
self.redis_ctl.set(key, value)
# 设置过期时间
self.redis_ctl.expire(key, self._expire_js_token)
logger.info('更新了 js_token')
def get_cache(self, key):
"""获取redis"""
try:
v = (self.redis_ctl.get(key)).decode('utf-8')
return v
except Exception as e:
logger.error('wxcache'+str(e))
return None
10、wxauthorize.py
from wxconfig import WxConfig
from urllib import parse
from wxlogger import logger
import requests
import json
""" 用于拦截 对页面的请求 提取用户信息"""
class WxAuthorServer(object):
"""微信网页授权server"""
"""对与请求连接进行重定向,获取用户信息进行网页授权"""
redirect_uri = '%s/wx/page/wxauthor' % WxConfig.AppHost
"""
应用授权作用域
snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)
snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
"""
SCOPE = 'snsapi_base'
"""通过code换取网页授权access_token"""
get_access_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?'
"""拉取用户信息"""
get_userinfo_url = 'https://api.weixin.qq.com/sns/userinfo?'
def get_code_url(self, state):
"""获取code的url"""
_dict = {'redirect_uri': self.redirect_uri}
redirect_uri = parse.urlencode(_dict)
author_get_code_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&%s&response_type=code&scope=%s&state=%s#wechat_redirect' % (WxConfig.AppID, redirect_uri, self.SCOPE, state)
return author_get_code_url
def get_auth_access_token(self, code):
"""通过code换取网页授权access_token"""
try:
url = self.get_access_token_url + 'appid=%s&secret=%s&code=%s&grant_type=authorization_code' % (WxConfig.AppID, WxConfig.AppSecret, code)
r = requests.get(url)
if r.status_code == 200:
json_res = json.loads(r.text)
if 'access_token' in json_res.keys():
return json_res
elif 'errcode' in json_res.keys():
errcode = json_res['errcode']
logger.error('通过code换取网页授权access_token:'+errcode)
except Exception as e:
logger.error('get_auth_access_token:'+str(e))
11、test.html
<!DOCTYPE HTML>
<html>
<!-- 这是一个标准的app页面 -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
<meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
<title>自定义页面-test</title>
<style>
</style>
</head>
<body>
<div>这是一个测试页</div>
</body>
<script type="text/javascript">
</script>
</html>
12、airkiss.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
<meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
<title>调用微信接口页面-airkiss</title>
<style>
</style>
</head>
<body>
<div>即将自动跳转。。。</div>
</body>
<script src="http://res2.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.f203.online/wx/sign');
xhr.send(null);
xhr.onload = function(e) {
if (xhr.status === 200) {
sign=JSON.parse(xhr.responseText)
wx.config({
beta: true, //开启内测接口调用,注入wx.invoke方法
debug: false, //关闭调试模式
appId: sign['appId'], //AppID
timestamp: sign['timestamp'], //时间戳
nonceStr: sign['nonceStr'], //随机串
signature: sign['signature'], //js-sdk签名
jsApiList: [
// 所有要调用的 API 都要加到这个列表中
'configWXDeviceWiFi'
]
});
wx.ready(function() {
// 在这里调用 API
wx.invoke('configWXDeviceWiFi');
});
wx.error(function(res) {
alert("配置出错");
});
} else {
alert('请求签名失败!');
}
}
xhr.onerror = function(e) {
alert('请求失败'+e)
}
</script>
</html>
接下来就是分析了,奉上测试号供大家观看3月15号后会关闭
现在公众号可以用了 我前几天更新了域名导致以前的域名没法使用 有些网页打不开
在实际运行中我将网页授权去掉了 直接进行页面跳转