提交 83947478a4281bb902e0b62acbb09fde15ddc990

作者 qianyingz
1 个父辈 8fe47fba

oidc用户认证接口

@@ -28,4 +28,5 @@ kservice/tmp @@ -28,4 +28,5 @@ kservice/tmp
28 dist/ 28 dist/
29 build/ 29 build/
30 *.egg-info/ 30 *.egg-info/
31 -.git/  
  31 +.git/
  32 +.vscode/
@@ -7,8 +7,8 @@ import time @@ -7,8 +7,8 @@ import time
7 import configure 7 import configure
8 from app.util import BlueprintApi 8 from app.util import BlueprintApi
9 from app.util import find_class 9 from app.util import find_class
10 -from app.models import db,Table,InsertingLayerName,Database,DES,Task  
11 - 10 +from app.models import db, Table, InsertingLayerName, Database, DES, Task
  11 +from app.modules.auth.oauth2 import config_oauth
12 from flasgger import Swagger 12 from flasgger import Swagger
13 # from rtree import index 13 # from rtree import index
14 import logging 14 import logging
@@ -31,12 +31,15 @@ import os @@ -31,12 +31,15 @@ import os
31 """ 31 """
32 因为decimal不能序列化,增加Flask对decimal类的解析 32 因为decimal不能序列化,增加Flask对decimal类的解析
33 """ 33 """
  34 +
  35 +
34 class JSONEncoder(_JSONEncoder): 36 class JSONEncoder(_JSONEncoder):
35 def default(self, o): 37 def default(self, o):
36 if isinstance(o, decimal.Decimal): 38 if isinstance(o, decimal.Decimal):
37 return float(o) 39 return float(o)
38 super(JSONEncoder, self).default(o) 40 super(JSONEncoder, self).default(o)
39 41
  42 +
40 class Flask(_Flask): 43 class Flask(_Flask):
41 json_encoder = JSONEncoder 44 json_encoder = JSONEncoder
42 45
@@ -52,12 +55,18 @@ def create_app(): @@ -52,12 +55,18 @@ def create_app():
52 app.config['echo'] = True 55 app.config['echo'] = True
53 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True 56 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
54 app.config['JSON_AS_ASCII'] = False 57 app.config['JSON_AS_ASCII'] = False
  58 + app.config['SECRET_KEY'] = configure.SECRET_KEY
  59 + app.config['OAUTH2_JWT_ENABLED'] = True
  60 +
  61 + app.config['OAUTH2_JWT_ISS'] = 'http://localhost:5000'
  62 + app.config['OAUTH2_JWT_KEY'] = 'secret-key'
  63 + app.config['OAUTH2_JWT_ALG'] = 'HS256'
55 # app.config['SQLALCHEMY_ECHO'] = True 64 # app.config['SQLALCHEMY_ECHO'] = True
56 65
57 # 跨域设置 66 # 跨域设置
58 CORS(app) 67 CORS(app)
59 68
60 - #swagger设置 69 + # swagger设置
61 swagger_config = Swagger.DEFAULT_CONFIG 70 swagger_config = Swagger.DEFAULT_CONFIG
62 swagger_config.update(configure.swagger_configure) 71 swagger_config.update(configure.swagger_configure)
63 Swagger(app, config=swagger_config) 72 Swagger(app, config=swagger_config)
@@ -66,41 +75,47 @@ def create_app(): @@ -66,41 +75,47 @@ def create_app():
66 db.init_app(app) 75 db.init_app(app)
67 db.create_all(app=app) 76 db.create_all(app=app)
68 77
69 -  
70 # 日志 78 # 日志
71 logging.basicConfig(level=logging.INFO) 79 logging.basicConfig(level=logging.INFO)
72 - log_file = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))),"logs","log.txt")  
73 - handler = logging.FileHandler(log_file, encoding='UTF-8') # 设置日志字符集和存储路径名字  
74 - logging_format = logging.Formatter('[%(levelname)s] %(asctime)s %(message)s') 80 + log_file = os.path.join(os.path.dirname(os.path.dirname(
  81 + os.path.realpath(__file__))), "logs", "log.txt")
  82 + handler = logging.FileHandler(
  83 + log_file, encoding='UTF-8') # 设置日志字符集和存储路径名字
  84 + logging_format = logging.Formatter(
  85 + '[%(levelname)s] %(asctime)s %(message)s')
75 handler.setFormatter(logging_format) 86 handler.setFormatter(logging_format)
76 app.logger.addHandler(handler) 87 app.logger.addHandler(handler)
77 -  
78 - 88 +
  89 + # 配置使用鉴权组件,不写无法认证授权
  90 + config_oauth(app)
  91 +
79 # 注册blueprint,查找BlueprintApi的子类 92 # 注册blueprint,查找BlueprintApi的子类
80 for scan in configure.scan_module: 93 for scan in configure.scan_module:
81 for api in find_class(scan, BlueprintApi): 94 for api in find_class(scan, BlueprintApi):
82 app.register_blueprint(api.bp) 95 app.register_blueprint(api.bp)
83 96
84 -  
85 # 入库监测线程 97 # 入库监测线程
  98 +
86 @app.before_first_request 99 @app.before_first_request
87 def data_entry_process(): 100 def data_entry_process():
88 StructurePrint.print("start listen") 101 StructurePrint.print("start listen")
89 process = threading.Thread(target=data_entry_center) 102 process = threading.Thread(target=data_entry_center)
90 process.start() 103 process.start()
  104 +
  105 + # 不检测https
  106 + os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
  107 +
91 108
92 return app 109 return app
93 110
94 111
95 -  
96 -  
97 def data_entry_center(): 112 def data_entry_center():
98 running_dict = {} 113 running_dict = {}
99 - sys_session: Session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) 114 + sys_session: Session = PGUtil.get_db_session(
  115 + configure.SQLALCHEMY_DATABASE_URI)
100 116
101 while True: 117 while True:
102 118
103 -  
104 try: 119 try:
105 time.sleep(3) 120 time.sleep(3)
106 121
@@ -109,10 +124,11 @@ def data_entry_center(): @@ -109,10 +124,11 @@ def data_entry_center():
109 124
110 # structured_print(running_dict.__len__().__str__()) 125 # structured_print(running_dict.__len__().__str__())
111 126
112 - for process,layer_names in running_dict.items(): 127 + for process, layer_names in running_dict.items():
113 if not process.is_alive(): 128 if not process.is_alive():
114 for l in layer_names: 129 for l in layer_names:
115 - inserted = sys_session.query(InsertingLayerName).filter_by(name=l).one_or_none() 130 + inserted = sys_session.query(
  131 + InsertingLayerName).filter_by(name=l).one_or_none()
116 if inserted: 132 if inserted:
117 sys_session.delete(inserted) 133 sys_session.delete(inserted)
118 sys_session.commit() 134 sys_session.commit()
@@ -124,38 +140,40 @@ def data_entry_center(): @@ -124,38 +140,40 @@ def data_entry_center():
124 140
125 # 入库进程少于阈值,开启入库进程 141 # 入库进程少于阈值,开启入库进程
126 142
127 - inter_size = sys_session.query(distinct(InsertingLayerName.task_guid)).count() 143 + inter_size = sys_session.query(
  144 + distinct(InsertingLayerName.task_guid)).count()
128 145
129 if inter_size < configure.entry_data_thread: 146 if inter_size < configure.entry_data_thread:
130 # 锁表啊 147 # 锁表啊
131 - ready_task:Task = sys_session.query(Task).filter_by(state=0).order_by(Task.create_time).with_lockmode("update").limit(1).one_or_none() 148 + ready_task: Task = sys_session.query(Task).filter_by(state=0).order_by(
  149 + Task.create_time).with_lockmode("update").limit(1).one_or_none()
132 if ready_task: 150 if ready_task:
133 151
134 try: 152 try:
135 parameter = json.loads(ready_task.parameter) 153 parameter = json.loads(ready_task.parameter)
136 StructurePrint.print("检测到入库任务") 154 StructurePrint.print("检测到入库任务")
137 - ready_task.state=2  
138 - ready_task.process="入库中" 155 + ready_task.state = 2
  156 + ready_task.process = "入库中"
139 sys_session.commit() 157 sys_session.commit()
140 158
141 - metas: list = json.loads(parameter.get("meta").__str__()) 159 + metas: list = json.loads(
  160 + parameter.get("meta").__str__())
142 parameter["meta"] = metas 161 parameter["meta"] = metas
143 162
144 -  
145 - database = sys_session.query(Database).filter_by(guid=ready_task.database_guid).one_or_none()  
146 - pg_ds: DataSource = PGUtil.open_pg_data_source(1,DES.decode(database.sqlalchemy_uri)) 163 + database = sys_session.query(Database).filter_by(
  164 + guid=ready_task.database_guid).one_or_none()
  165 + pg_ds: DataSource = PGUtil.open_pg_data_source(
  166 + 1, DES.decode(database.sqlalchemy_uri))
147 167
148 this_task_layer = [] 168 this_task_layer = []
149 for meta in metas: 169 for meta in metas:
150 overwrite = parameter.get("overwrite", "no") 170 overwrite = parameter.get("overwrite", "no")
151 171
152 -  
153 -  
154 for layer_name_origin, layer_name in meta.get("layer").items(): 172 for layer_name_origin, layer_name in meta.get("layer").items():
155 origin_name = layer_name 173 origin_name = layer_name
156 no = 1 174 no = 1
157 175
158 - while (overwrite.__eq__("no") and pg_ds.GetLayerByName(layer_name)) or sys_session.query(InsertingLayerName).filter_by(name=layer_name).one_or_none() : 176 + while (overwrite.__eq__("no") and pg_ds.GetLayerByName(layer_name)) or sys_session.query(InsertingLayerName).filter_by(name=layer_name).one_or_none():
159 layer_name = origin_name + "_{}".format(no) 177 layer_name = origin_name + "_{}".format(no)
160 no += 1 178 no += 1
161 179
@@ -171,7 +189,8 @@ def data_entry_center(): @@ -171,7 +189,8 @@ def data_entry_center():
171 meta["layer"][layer_name_origin] = layer_name 189 meta["layer"][layer_name_origin] = layer_name
172 190
173 pg_ds.Destroy() 191 pg_ds.Destroy()
174 - entry_data_process = multiprocessing.Process(target=EntryDataVacuate().entry,args=(parameter,)) 192 + entry_data_process = multiprocessing.Process(
  193 + target=EntryDataVacuate().entry, args=(parameter,))
175 entry_data_process.start() 194 entry_data_process.start()
176 running_dict[entry_data_process] = this_task_layer 195 running_dict[entry_data_process] = this_task_layer
177 except Exception as e: 196 except Exception as e:
@@ -184,4 +203,4 @@ def data_entry_center(): @@ -184,4 +203,4 @@ def data_entry_center():
184 sys_session.commit() 203 sys_session.commit()
185 except Exception as e: 204 except Exception as e:
186 sys_session.commit() 205 sys_session.commit()
187 - StructurePrint.print(e.__str__(),"error")  
  206 + StructurePrint.print(e.__str__(), "error")
  1 +from app.util import BlueprintApi
  2 +from app.util import BlueprintApi
  3 +from flask import Blueprint, render_template, redirect, url_for, request, session, jsonify
  4 +from .models import *
  5 +from werkzeug.security import gen_salt
  6 +import time
  7 +from .oauth2 import authorization, require_oauth, generate_user_info
  8 +from authlib.oauth2 import OAuth2Error
  9 +from authlib.integrations.flask_oauth2 import current_token
  10 +
  11 +def current_user():
  12 + if 'id' in session:
  13 + uid = session['id']
  14 + return User.query.get(uid)
  15 + return None
  16 +
  17 +
  18 +def split_by_crlf(s):
  19 + return [v for v in s.splitlines() if v]
  20 +
  21 +
  22 +class DataManager(BlueprintApi):
  23 + bp = Blueprint("Auth", __name__, url_prefix="/auth")
  24 +
  25 + @staticmethod
  26 + @bp.route('/test', methods=('GET', 'POST'))
  27 + def Test():
  28 + res = {}
  29 + try:
  30 + res['user'] = User.query.all()
  31 + except Exception as e:
  32 + raise e
  33 + return res
  34 +
  35 + @staticmethod
  36 + @bp.route('/', methods=('GET', 'POST'))
  37 + def test():
  38 + if request.method == 'POST':
  39 + username = request.form['username']
  40 + password = request.form['password']
  41 + user = User.query.filter_by(username=username).first()
  42 + if not user:
  43 + user = User(username=username,
  44 + password=password, role='admin')
  45 + db.session.add(user)
  46 + db.session.commit()
  47 + session['id'] = user.id
  48 + return redirect('/auth')
  49 + user = current_user()
  50 + if user:
  51 + clients = OAuth2Client.query.filter_by(user_id=user.id).all()
  52 + else:
  53 + clients = []
  54 + return render_template('auth/login.html', user=user, clients=clients)
  55 +
  56 +
  57 +
  58 + @staticmethod
  59 + @bp.route('/create_client', methods=('GET', 'POST'))
  60 + def create_client():
  61 + user = current_user()
  62 + if not user:
  63 + return redirect('/auth')
  64 + if request.method == 'GET':
  65 + return render_template('auth/create_client.html')
  66 + form = request.form
  67 + client_id = gen_salt(24)
  68 + client = OAuth2Client(client_id=client_id, user_id=user.id)
  69 + # Mixin doesn't set the issue_at date
  70 + client.client_id_issued_at = int(time.time())
  71 + if client.token_endpoint_auth_method == 'none':
  72 + client.client_secret = ''
  73 + else:
  74 + client.client_secret = gen_salt(48)
  75 + client_metadata = {
  76 + "client_name": form["client_name"],
  77 + "client_uri": form["client_uri"],
  78 + "grant_types": split_by_crlf(form["grant_type"]),
  79 + "redirect_uris": split_by_crlf(form["redirect_uri"]),
  80 + "response_types": split_by_crlf(form["response_type"]),
  81 + "scope": form["scope"],
  82 + "token_endpoint_auth_method": form["token_endpoint_auth_method"]
  83 + }
  84 + client.set_client_metadata(client_metadata)
  85 + db.session.add(client)
  86 + db.session.commit()
  87 + return redirect('/auth')
  88 +
  89 + @staticmethod
  90 + @bp.route('/authorize', methods=('GET', 'POST'))
  91 + def authorize():
  92 + user = current_user()
  93 + if request.method == 'GET':
  94 + try:
  95 + grant = authorization.validate_consent_request(end_user=user)
  96 + except OAuth2Error as error:
  97 + return jsonify(dict(error.get_body()))
  98 + return render_template('auth/authorize.html', user=user, grant=grant)
  99 + if not user and 'username' in request.form:
  100 + username = request.form.get('username')
  101 + user = User.query.filter_by(username=username).first()
  102 + if request.form['confirm']:
  103 + grant_user = user
  104 + else:
  105 + grant_user = None
  106 + return authorization.create_authorization_response(grant_user=grant_user)
  107 +
  108 +
  109 + @staticmethod
  110 + @bp.route('/token', methods=['POST'])
  111 + def issue_token():
  112 + return authorization.create_token_response()
  113 +
  114 + @staticmethod
  115 + @bp.route('/userinfo')
  116 + @require_oauth('profile')
  117 + def api_me():
  118 + return jsonify(generate_user_info(current_token.user, current_token.scope))
  1 +from flask_sqlalchemy import sqlalchemy
  2 +from sqlalchemy import Column, Integer, Text, Time, ForeignKey
  3 +from app.models import db
  4 +from authlib.integrations.sqla_oauth2 import (
  5 + OAuth2ClientMixin,
  6 + OAuth2TokenMixin,
  7 + OAuth2AuthorizationCodeMixin
  8 +)
  9 +from sqlalchemy.orm import relationship
  10 +
  11 +
  12 +class User (db.Model):
  13 + '''
  14 + 用户信息表
  15 + '''
  16 + __tablename__ = "dmdms_user"
  17 + id = Column(Integer, primary_key=True)
  18 + username = Column(Text)
  19 + password = Column(Text)
  20 + company = Column(Text)
  21 + position = Column(Text)
  22 + phone = Column(Text)
  23 + email = Column(Text)
  24 + create_time = Column(Time)
  25 + update_time = Column(Time)
  26 + role = Column(Text)
  27 +
  28 + def __str__(self):
  29 + return self.username
  30 +
  31 + def get_user_id(self):
  32 + return self.id
  33 +
  34 +
  35 +class OAuth2Client(db.Model, OAuth2ClientMixin):
  36 + __tablename__ = 'oauth2_client'
  37 +
  38 + id = Column(Integer, primary_key=True)
  39 + user_id = Column(
  40 + Integer, ForeignKey('dmdms_user.id', ondelete='CASCADE'))
  41 + user = relationship('User')
  42 +
  43 +
  44 +class OAuth2AuthorizationCode(db.Model, OAuth2AuthorizationCodeMixin):
  45 + __tablename__ = 'oauth2_code'
  46 +
  47 + id = Column(Integer, primary_key=True)
  48 + user_id = Column(
  49 + Integer, ForeignKey('dmdms_user.id', ondelete='CASCADE'))
  50 + user = relationship('User')
  51 +
  52 +
  53 +class OAuth2Token(db.Model, OAuth2TokenMixin):
  54 + __tablename__ = 'oauth2_token'
  55 +
  56 + id = Column(Integer, primary_key=True)
  57 + user_id = Column(
  58 + Integer, ForeignKey('dmdms_user.id', ondelete='CASCADE'))
  59 + user = relationship('User')
  1 +from authlib.integrations.flask_oauth2 import (
  2 + AuthorizationServer, ResourceProtector)
  3 +from authlib.integrations.sqla_oauth2 import (
  4 + create_query_client_func,
  5 + create_save_token_func,
  6 + create_bearer_token_validator,
  7 +)
  8 +from authlib.oauth2.rfc6749.grants import (
  9 + AuthorizationCodeGrant as _AuthorizationCodeGrant,
  10 +)
  11 +from authlib.oidc.core.grants import (
  12 + OpenIDCode as _OpenIDCode,
  13 + OpenIDImplicitGrant as _OpenIDImplicitGrant,
  14 + OpenIDHybridGrant as _OpenIDHybridGrant,
  15 +)
  16 +from authlib.oidc.core import UserInfo
  17 +from werkzeug.security import gen_salt
  18 +from .models import db, User
  19 +from .models import OAuth2Client, OAuth2AuthorizationCode, OAuth2Token
  20 +
  21 +
  22 +DUMMY_JWT_CONFIG = {
  23 + 'key': 'secret-key',
  24 + 'alg': 'HS256',
  25 + 'iss': 'https://authlib.org',
  26 + 'exp': 7200,
  27 +}
  28 +
  29 +def exists_nonce(nonce, req):
  30 + exists = OAuth2AuthorizationCode.query.filter_by(
  31 + client_id=req.client_id, nonce=nonce
  32 + ).first()
  33 + return bool(exists)
  34 +
  35 +
  36 +def generate_user_info(user, scope):
  37 + return UserInfo(sub=str(user.id), name=user.username)
  38 +
  39 +
  40 +def create_authorization_code(client, grant_user, request):
  41 + code = gen_salt(48)
  42 + nonce = request.data.get('nonce')
  43 + item = OAuth2AuthorizationCode(
  44 + code=code,
  45 + client_id=client.client_id,
  46 + redirect_uri=request.redirect_uri,
  47 + scope=request.scope,
  48 + user_id=grant_user.id,
  49 + nonce=nonce,
  50 + )
  51 + db.session.add(item)
  52 + db.session.commit()
  53 + return code
  54 +
  55 +
  56 +class AuthorizationCodeGrant(_AuthorizationCodeGrant):
  57 + def create_authorization_code(self, client, grant_user, request):
  58 + return create_authorization_code(client, grant_user, request)
  59 +
  60 + def parse_authorization_code(self, code, client):
  61 + item = OAuth2AuthorizationCode.query.filter_by(
  62 + code=code, client_id=client.client_id).first()
  63 + if item and not item.is_expired():
  64 + return item
  65 +
  66 + def delete_authorization_code(self, authorization_code):
  67 + db.session.delete(authorization_code)
  68 + db.session.commit()
  69 +
  70 + def authenticate_user(self, authorization_code):
  71 + return User.query.get(authorization_code.user_id)
  72 +
  73 +
  74 +class OpenIDCode(_OpenIDCode):
  75 + def exists_nonce(self, nonce, request):
  76 + return exists_nonce(nonce, request)
  77 +
  78 + def get_jwt_config(self, grant):
  79 + return DUMMY_JWT_CONFIG
  80 +
  81 + def generate_user_info(self, user, scope):
  82 + return generate_user_info(user, scope)
  83 +
  84 +
  85 +class ImplicitGrant(_OpenIDImplicitGrant):
  86 + def exists_nonce(self, nonce, request):
  87 + return exists_nonce(nonce, request)
  88 +
  89 + def get_jwt_config(self, grant):
  90 + return DUMMY_JWT_CONFIG
  91 +
  92 + def generate_user_info(self, user, scope):
  93 + return generate_user_info(user, scope)
  94 +
  95 +
  96 +class HybridGrant(_OpenIDHybridGrant):
  97 + def create_authorization_code(self, client, grant_user, request):
  98 + return create_authorization_code(client, grant_user, request)
  99 +
  100 + def exists_nonce(self, nonce, request):
  101 + return exists_nonce(nonce, request)
  102 +
  103 + def get_jwt_config(self):
  104 + return DUMMY_JWT_CONFIG
  105 +
  106 + def generate_user_info(self, user, scope):
  107 + return generate_user_info(user, scope)
  108 +
  109 +
  110 +authorization = AuthorizationServer()
  111 +require_oauth = ResourceProtector()
  112 +
  113 +
  114 +def config_oauth(app):
  115 + query_client = create_query_client_func(db.session, OAuth2Client)
  116 + save_token = create_save_token_func(db.session, OAuth2Token)
  117 + authorization.init_app(
  118 + app,
  119 + query_client=query_client,
  120 + save_token=save_token
  121 + )
  122 +
  123 + # support all openid grants
  124 + authorization.register_grant(AuthorizationCodeGrant, [
  125 + OpenIDCode(require_nonce=True),
  126 + ])
  127 + authorization.register_grant(ImplicitGrant)
  128 + authorization.register_grant(HybridGrant)
  129 +
  130 + # protect resource
  131 + bearer_cls = create_bearer_token_validator(db.session, OAuth2Token)
  132 + require_oauth.register_token_validator(bearer_cls())
  1 +<p>{{grant.client.client_name}} is requesting:
  2 +<strong>{{ grant.request.scope }}</strong>
  3 +</p>
  4 +
  5 +<form action="" method="post">
  6 + <label>
  7 + <input type="checkbox" name="confirm">
  8 + <span>Consent?</span>
  9 + </label>
  10 + {% if not user %}
  11 + <p>You haven't logged in. Log in with:</p>
  12 + <div>
  13 + <input type="text" name="username">
  14 + </div>
  15 + {% endif %}
  16 + <br>
  17 + <button>Submit</button>
  18 +</form>
  1 +<style>
  2 + label, label > span { display: block; }
  3 + label { margin: 15px 0; }
  4 +</style>
  5 +
  6 +<a href="/">Home</a>
  7 +
  8 +<form action="" method="post">
  9 + <label>
  10 + <span>Client Name</span>
  11 + <input type="text" name="client_name">
  12 + </label>
  13 + <label>
  14 + <span>Client URI</span>
  15 + <input type="url" name="client_uri">
  16 + </label>
  17 + <label>
  18 + <span>Allowed Scope</span>
  19 + <input type="text" name="scope">
  20 + </label>
  21 + <label>
  22 + <span>Redirect URIs</span>
  23 + <textarea name="redirect_uri" cols="30" rows="10"></textarea>
  24 + </label>
  25 + <label>
  26 + <span>Allowed Grant Types</span>
  27 + <textarea name="grant_type" cols="30" rows="10"></textarea>
  28 + </label>
  29 + <label>
  30 + <span>Allowed Response Types</span>
  31 + <textarea name="response_type" cols="30" rows="10"></textarea>
  32 + </label>
  33 + <label>
  34 + <span>Token Endpoint Auth Method</span>
  35 + <select name="token_endpoint_auth_method">
  36 + <option value="client_secret_basic">client_secret_basic</option>
  37 + <option value="client_secret_post">client_secret_post</option>
  38 + <option value="none">none</option>
  39 + </select>
  40 + </label>
  41 + <button>Submit</button>
  42 +</form>
  1 +{% if user %}
  2 + <style>pre{white-space:wrap}</style>
  3 +<div>Logged in as <strong>{{user}}</strong></div>
  4 +
  5 +{% for client in clients %}
  6 +<pre>
  7 +{{ client.client_info|tojson }}
  8 +{{ client.client_metadata|tojson }}
  9 +</pre>
  10 +<hr>
  11 +{% endfor %}
  12 +
  13 +<br><a href="{{ url_for('.create_client') }}">Create Client</a>
  14 +
  15 +{% else %}
  16 +<form action="" method="post">
  17 + <input type="text" name="username" placeholder="账号">
  18 + <input type="text" name="password" placeholder="密码">
  19 + <button type="submit">Login / Signup</button>
  20 +</form>
  21 +{% endif %}
@@ -3,15 +3,16 @@ @@ -3,15 +3,16 @@
3 # 程序部署ip:host 3 # 程序部署ip:host
4 deploy_ip_host = "172.26.99.160:8840" 4 deploy_ip_host = "172.26.99.160:8840"
5 # 系统数据库 5 # 系统数据库
6 -SQLALCHEMY_DATABASE_URI = "postgresql://postgres:chinadci@172.26.99.160:5432/dmap_dms_test" 6 +SQLALCHEMY_DATABASE_URI = "postgresql://postgres:postgres@172.26.40.254:5433/dmap_dms_test"
7 7
8 8
9 # 部署模式cluster,standalone 9 # 部署模式cluster,standalone
10 -deployment_mode="cluster" 10 +deployment_mode = "cluster"
11 # 部署模式味cluster时有用,master,slave 11 # 部署模式味cluster时有用,master,slave
12 -application_name="master" 12 +application_name = "master"
13 13
14 # 固定配置不需要修改 14 # 固定配置不需要修改
15 -swagger_configure={"title":"DMapManager"} 15 +swagger_configure = {"title": "DMapManager"}
16 entry_data_thread = 3 16 entry_data_thread = 3
17 -scan_module = ["app.modules"]# API所在的模块 17 +scan_module = ["app.modules"] # API所在的模块
  18 +SECRET_KEY = b'_5#y2L"F4Q8z\n\xec]/'
1 flask==1.1.2 1 flask==1.1.2
2 SQLAlchemy==1.3.17 2 SQLAlchemy==1.3.17
3 Flask-SQLAlchemy==2.4.3 3 Flask-SQLAlchemy==2.4.3
4 -gevent==20.9.0 4 +#gevent==20.9.0
5 gunicorn==20.0.4 5 gunicorn==20.0.4
6 flask_cors==3.0.8 6 flask_cors==3.0.8
7 flasgger==0.9.5 7 flasgger==0.9.5
8 -GDAL==3.2.1 8 +#GDAL==3.2.1
9 psycopg2==2.8.5 9 psycopg2==2.8.5
10 pyDes==2.0.1 10 pyDes==2.0.1
11 gevent-websocket==0.10.1 11 gevent-websocket==0.10.1
12 Pillow==8.1.2 12 Pillow==8.1.2
13 #Rtree==0.9.7 13 #Rtree==0.9.7
14 opencv-python==4.5.1.48 14 opencv-python==4.5.1.48
15 -pstuil==5.8.0  
16 -mod_wsgi==4.8.0  
  15 +psutil==5.8.0
  16 +#mod_wsgi==4.8.0
  17 +Authlib==0.13
@@ -3,5 +3,4 @@ from flask import Flask @@ -3,5 +3,4 @@ from flask import Flask
3 from app import create_app 3 from app import create_app
4 app:Flask = create_app() 4 app:Flask = create_app()
5 if __name__ == '__main__': 5 if __name__ == '__main__':
6 - app.run(host="0.0.0.0", port="8840", threaded=True, debug=True)  
7 - 6 + app.run(host="0.0.0.0", port="8840", threaded=True, debug=True)
注册登录 后发表评论