Skip to content

Commit

Permalink
Merge pull request #90 from RegimenArsenic/master
Browse files Browse the repository at this point in the history
初步增加web-http聊天功能
  • Loading branch information
zhayujie authored Mar 7, 2023
2 parents 4971e3a + 0b42083 commit 6bbaaf6
Show file tree
Hide file tree
Showing 10 changed files with 794 additions and 1 deletion.
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
**应用:**

- [x] [终端](https://github.com/zhayujie/bot-on-anything#1%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%BB%88%E7%AB%AF)
- [ ] Web
- [x] [Web](https://github.com/zhayujie/bot-on-anything#9web)
- [x] [个人微信](https://github.com/zhayujie/bot-on-anything#2%E4%B8%AA%E4%BA%BA%E5%BE%AE%E4%BF%A1)
- [x] [订阅号](https://github.com/zhayujie/bot-on-anything#3%E4%B8%AA%E4%BA%BA%E8%AE%A2%E9%98%85%E5%8F%B7)
- [x] [服务号](https://github.com/zhayujie/bot-on-anything#4%E4%BC%81%E4%B8%9A%E6%9C%8D%E5%8A%A1%E5%8F%B7)
Expand Down Expand Up @@ -393,3 +393,35 @@ http:/你的固定公网ip或者域名:端口/slack/events
```
https://slack.dev/bolt-python/tutorial/getting-started
```
### 9.Web
#### http
**需要:** 服务器
**依赖**
```bash
pip3 install PyJWT flask
```
**配置**
```bash
"channel": {
"type": "http",
"http": {
"http_auth_secret_key": "6d25a684-9558-11e9-aa94-efccd7a0659b",//jwt认证秘钥
"http_auth_password": "6.67428e-11",//认证密码,仅仅只是自用,最初步的防御别人扫描端口后DDOS浪费tokens
"port": "80"//端口
}
}
```
URL,如果端口是 80 ,可不填
```
http:/你的固定公网ip或者域名:端口/
```
4 changes: 4 additions & 0 deletions channel/channel_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ def create_channel(channel_type):
from channel.slack.slack_channel import SlackChannel
return SlackChannel()

elif channel_type == const.HTTP:
from channel.http.http_channel import HttpChannel
return HttpChannel()

else:
raise RuntimeError
107 changes: 107 additions & 0 deletions channel/http/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# encoding:utf-8

import jwt
import datetime
import time
from flask import jsonify, request
from common import const
from config import channel_conf


class Auth():
def __init__(self, login):
# argument 'privilegeRequired' is to set up your method's privilege
# name
self.login = login
super(Auth, self).__init__()

@staticmethod
def encode_auth_token(user_id, login_time):
"""
生成认证Token
:param user_id: int
:param login_time: datetime
:return: string
"""
try:
payload = {
'iss': 'ken', # 签名
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=0, hours=10), # 过期时间
'iat': datetime.datetime.utcnow(), # 开始时间
'data': {
'id': user_id,
'login_time': login_time
}
}
return jwt.encode(
payload,
channel_conf(const.HTTP).get('http_auth_secret_key'),
algorithm='HS256'
) # 加密生成字符串
except Exception as e:
return e

@staticmethod
def decode_auth_token(auth_token):
"""
验证Token
:param auth_token:
:return: integer|string
"""
try:
# 取消过期时间验证
payload = jwt.decode(auth_token, channel_conf(const.HTTP).get(
'http_auth_secret_key'), algorithms='HS256') # options={'verify_exp': False} 加上后不验证token过期时间
if ('data' in payload and 'id' in payload['data']):
return payload
else:
raise jwt.InvalidTokenError
except jwt.ExpiredSignatureError:
return 'Token过期'
except jwt.InvalidTokenError:
return '无效Token'


def authenticate(password):
"""
用户登录,登录成功返回token
:param password:
:return: json
"""
authPassword = channel_conf(const.HTTP).get('http_auth_password')
if (authPassword != password):
return False
else:
login_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
token = Auth.encode_auth_token(password, login_time)
return token


def identify(request):
"""
用户鉴权
:return: list
"""
try:
if (request is None):
return False
authorization = request.cookies.get('Authorization')
if (authorization):
payload = Auth.decode_auth_token(authorization)
if not isinstance(payload, str):
authPassword = channel_conf(
const.HTTP).get('http_auth_password')
password = payload['data']['id']
if (password != authPassword):
return False
else:
return True
return False

except jwt.ExpiredSignatureError:
#result = 'Token已更改,请重新登录获取'
return False

except jwt.InvalidTokenError:
#result = '没有提供认证token'
return False
66 changes: 66 additions & 0 deletions channel/http/http_channel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# encoding:utf-8

import json
from channel.http import auth
from flask import Flask, request, render_template, make_response
from datetime import timedelta
from common import const
from config import channel_conf
from channel.channel import Channel
http_app = Flask(__name__,)
# 自动重载模板文件
http_app.jinja_env.auto_reload = True
http_app.config['TEMPLATES_AUTO_RELOAD'] = True

# 设置静态文件缓存过期时间
http_app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=1)


@http_app.route("/chat", methods=['POST'])
def chat():
if (auth.identify(request) == False):
return
data = json.loads(request.data)
if data:
msg = data['msg']
if not msg:
return
reply_text = HttpChannel().handle(data=data)
return {'result': reply_text}


@http_app.route("/", methods=['GET'])
def index():
if (auth.identify(request) == False):
return login()
return render_template('index.html')


@http_app.route("/login", methods=['POST', 'GET'])
def login():
response = make_response("<html></html>",301)
response.headers.add_header('content-type','text/plain')
response.headers.add_header('location','./')
if (auth.identify(request) == True):
return response
else:
if request.method == "POST":
token = auth.authenticate(request.form['password'])
if (token != False):
response.set_cookie(key='Authorization', value=token)
return response
else:
return render_template('login.html')
response.headers.set('location','./login?err=登录失败')
return response

class HttpChannel(Channel):
def startup(self):
http_app.run(host='0.0.0.0', port=channel_conf(const.HTTP).get('port'))

def handle(self, data):
context = dict()
id = data["id"]
context['from_user_id'] = str(id)
return super().build_reply_content(data["msg"], context)

Loading

0 comments on commit 6bbaaf6

Please sign in to comment.