正在显示
11 个修改的文件
包含
468 行增加
和
52 行删除
@@ -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 |
@@ -28,6 +28,13 @@ from app.util.component.StructuredPrint import StructurePrint | @@ -28,6 +28,13 @@ from app.util.component.StructuredPrint import StructurePrint | ||
28 | from app.util.component.PGUtil import PGUtil | 28 | from app.util.component.PGUtil import PGUtil |
29 | import os | 29 | import os |
30 | 30 | ||
31 | +<<<<<<< HEAD | ||
32 | +======= | ||
33 | +""" | ||
34 | +因为decimal不能序列化,增加Flask对decimal类的解析 | ||
35 | +""" | ||
36 | + | ||
37 | +>>>>>>> 62c596fe02f871582dc30904695c665d1c3fc006 | ||
31 | 38 | ||
32 | class JSONEncoder(_JSONEncoder): | 39 | class JSONEncoder(_JSONEncoder): |
33 | """ | 40 | """ |
@@ -38,6 +45,7 @@ class JSONEncoder(_JSONEncoder): | @@ -38,6 +45,7 @@ class JSONEncoder(_JSONEncoder): | ||
38 | return float(o) | 45 | return float(o) |
39 | super(JSONEncoder, self).default(o) | 46 | super(JSONEncoder, self).default(o) |
40 | 47 | ||
48 | + | ||
41 | class Flask(_Flask): | 49 | class Flask(_Flask): |
42 | json_encoder = JSONEncoder | 50 | json_encoder = JSONEncoder |
43 | 51 | ||
@@ -57,12 +65,18 @@ def create_app(): | @@ -57,12 +65,18 @@ def create_app(): | ||
57 | app.config['echo'] = True | 65 | app.config['echo'] = True |
58 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True | 66 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True |
59 | app.config['JSON_AS_ASCII'] = False | 67 | app.config['JSON_AS_ASCII'] = False |
68 | + app.config['SECRET_KEY'] = configure.SECRET_KEY | ||
69 | + app.config['OAUTH2_JWT_ENABLED'] = True | ||
70 | + | ||
71 | + app.config['OAUTH2_JWT_ISS'] = 'http://localhost:5000' | ||
72 | + app.config['OAUTH2_JWT_KEY'] = 'secret-key' | ||
73 | + app.config['OAUTH2_JWT_ALG'] = 'HS256' | ||
60 | # app.config['SQLALCHEMY_ECHO'] = True | 74 | # app.config['SQLALCHEMY_ECHO'] = True |
61 | 75 | ||
62 | # 跨域设置 | 76 | # 跨域设置 |
63 | CORS(app) | 77 | CORS(app) |
64 | 78 | ||
65 | - #swagger设置 | 79 | + # swagger设置 |
66 | swagger_config = Swagger.DEFAULT_CONFIG | 80 | swagger_config = Swagger.DEFAULT_CONFIG |
67 | swagger_config.update(configure.swagger_configure) | 81 | swagger_config.update(configure.swagger_configure) |
68 | Swagger(app, config=swagger_config) | 82 | Swagger(app, config=swagger_config) |
@@ -71,41 +85,47 @@ def create_app(): | @@ -71,41 +85,47 @@ def create_app(): | ||
71 | db.init_app(app) | 85 | db.init_app(app) |
72 | db.create_all(app=app) | 86 | db.create_all(app=app) |
73 | 87 | ||
74 | - | ||
75 | # 日志 | 88 | # 日志 |
76 | logging.basicConfig(level=logging.INFO) | 89 | logging.basicConfig(level=logging.INFO) |
77 | - log_file = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))),"logs","log.txt") | ||
78 | - handler = logging.FileHandler(log_file, encoding='UTF-8') # 设置日志字符集和存储路径名字 | ||
79 | - logging_format = logging.Formatter('[%(levelname)s] %(asctime)s %(message)s') | 90 | + log_file = os.path.join(os.path.dirname(os.path.dirname( |
91 | + os.path.realpath(__file__))), "logs", "log.txt") | ||
92 | + handler = logging.FileHandler( | ||
93 | + log_file, encoding='UTF-8') # 设置日志字符集和存储路径名字 | ||
94 | + logging_format = logging.Formatter( | ||
95 | + '[%(levelname)s] %(asctime)s %(message)s') | ||
80 | handler.setFormatter(logging_format) | 96 | handler.setFormatter(logging_format) |
81 | app.logger.addHandler(handler) | 97 | app.logger.addHandler(handler) |
82 | - | ||
83 | - | 98 | + |
99 | + # 配置使用鉴权组件,不写无法认证授权 | ||
100 | + config_oauth(app) | ||
101 | + | ||
84 | # 注册blueprint,查找BlueprintApi的子类 | 102 | # 注册blueprint,查找BlueprintApi的子类 |
85 | for scan in configure.scan_module: | 103 | for scan in configure.scan_module: |
86 | for api in find_class(scan, BlueprintApi): | 104 | for api in find_class(scan, BlueprintApi): |
87 | app.register_blueprint(api.bp) | 105 | app.register_blueprint(api.bp) |
88 | 106 | ||
89 | - | ||
90 | # 入库监测线程 | 107 | # 入库监测线程 |
108 | + | ||
91 | @app.before_first_request | 109 | @app.before_first_request |
92 | def data_entry_process(): | 110 | def data_entry_process(): |
93 | StructurePrint.print("start listen") | 111 | StructurePrint.print("start listen") |
94 | process = threading.Thread(target=data_entry_center) | 112 | process = threading.Thread(target=data_entry_center) |
95 | process.start() | 113 | process.start() |
114 | + | ||
115 | + # 不检测https | ||
116 | + os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' | ||
117 | + | ||
96 | 118 | ||
97 | return app | 119 | return app |
98 | 120 | ||
99 | 121 | ||
100 | - | ||
101 | - | ||
102 | def data_entry_center(): | 122 | def data_entry_center(): |
103 | running_dict = {} | 123 | running_dict = {} |
104 | - sys_session: Session = PGUtil.get_db_session(configure.SQLALCHEMY_DATABASE_URI) | 124 | + sys_session: Session = PGUtil.get_db_session( |
125 | + configure.SQLALCHEMY_DATABASE_URI) | ||
105 | 126 | ||
106 | while True: | 127 | while True: |
107 | 128 | ||
108 | - | ||
109 | try: | 129 | try: |
110 | time.sleep(3) | 130 | time.sleep(3) |
111 | 131 | ||
@@ -114,10 +134,11 @@ def data_entry_center(): | @@ -114,10 +134,11 @@ def data_entry_center(): | ||
114 | 134 | ||
115 | # structured_print(running_dict.__len__().__str__()) | 135 | # structured_print(running_dict.__len__().__str__()) |
116 | 136 | ||
117 | - for process,layer_names in running_dict.items(): | 137 | + for process, layer_names in running_dict.items(): |
118 | if not process.is_alive(): | 138 | if not process.is_alive(): |
119 | for l in layer_names: | 139 | for l in layer_names: |
120 | - inserted = sys_session.query(InsertingLayerName).filter_by(name=l).one_or_none() | 140 | + inserted = sys_session.query( |
141 | + InsertingLayerName).filter_by(name=l).one_or_none() | ||
121 | if inserted: | 142 | if inserted: |
122 | sys_session.delete(inserted) | 143 | sys_session.delete(inserted) |
123 | sys_session.commit() | 144 | sys_session.commit() |
@@ -129,7 +150,8 @@ def data_entry_center(): | @@ -129,7 +150,8 @@ def data_entry_center(): | ||
129 | 150 | ||
130 | # 入库进程少于阈值,开启入库进程 | 151 | # 入库进程少于阈值,开启入库进程 |
131 | 152 | ||
132 | - inter_size = sys_session.query(distinct(InsertingLayerName.task_guid)).count() | 153 | + inter_size = sys_session.query( |
154 | + distinct(InsertingLayerName.task_guid)).count() | ||
133 | 155 | ||
134 | if inter_size < configure.entry_data_thread: | 156 | if inter_size < configure.entry_data_thread: |
135 | # 锁表啊 | 157 | # 锁表啊 |
@@ -139,28 +161,28 @@ def data_entry_center(): | @@ -139,28 +161,28 @@ def data_entry_center(): | ||
139 | try: | 161 | try: |
140 | parameter = json.loads(ready_task.parameter) | 162 | parameter = json.loads(ready_task.parameter) |
141 | StructurePrint.print("检测到入库任务") | 163 | StructurePrint.print("检测到入库任务") |
142 | - ready_task.state=2 | ||
143 | - ready_task.process="入库中" | 164 | + ready_task.state = 2 |
165 | + ready_task.process = "入库中" | ||
144 | sys_session.commit() | 166 | sys_session.commit() |
145 | 167 | ||
146 | - metas: list = json.loads(parameter.get("meta").__str__()) | 168 | + metas: list = json.loads( |
169 | + parameter.get("meta").__str__()) | ||
147 | parameter["meta"] = metas | 170 | parameter["meta"] = metas |
148 | 171 | ||
149 | - | ||
150 | - database = sys_session.query(Database).filter_by(guid=ready_task.database_guid).one_or_none() | ||
151 | - pg_ds: DataSource = PGUtil.open_pg_data_source(1,DES.decode(database.sqlalchemy_uri)) | 172 | + database = sys_session.query(Database).filter_by( |
173 | + guid=ready_task.database_guid).one_or_none() | ||
174 | + pg_ds: DataSource = PGUtil.open_pg_data_source( | ||
175 | + 1, DES.decode(database.sqlalchemy_uri)) | ||
152 | 176 | ||
153 | this_task_layer = [] | 177 | this_task_layer = [] |
154 | for meta in metas: | 178 | for meta in metas: |
155 | overwrite = parameter.get("overwrite", "no") | 179 | overwrite = parameter.get("overwrite", "no") |
156 | 180 | ||
157 | - | ||
158 | - | ||
159 | for layer_name_origin, layer_name in meta.get("layer").items(): | 181 | for layer_name_origin, layer_name in meta.get("layer").items(): |
160 | origin_name = layer_name | 182 | origin_name = layer_name |
161 | no = 1 | 183 | no = 1 |
162 | 184 | ||
163 | - while (overwrite.__eq__("no") and pg_ds.GetLayerByName(layer_name)) or sys_session.query(InsertingLayerName).filter_by(name=layer_name).one_or_none() : | 185 | + while (overwrite.__eq__("no") and pg_ds.GetLayerByName(layer_name)) or sys_session.query(InsertingLayerName).filter_by(name=layer_name).one_or_none(): |
164 | layer_name = origin_name + "_{}".format(no) | 186 | layer_name = origin_name + "_{}".format(no) |
165 | no += 1 | 187 | no += 1 |
166 | 188 | ||
@@ -176,7 +198,8 @@ def data_entry_center(): | @@ -176,7 +198,8 @@ def data_entry_center(): | ||
176 | meta["layer"][layer_name_origin] = layer_name | 198 | meta["layer"][layer_name_origin] = layer_name |
177 | 199 | ||
178 | pg_ds.Destroy() | 200 | pg_ds.Destroy() |
179 | - entry_data_process = multiprocessing.Process(target=EntryDataVacuate().entry,args=(parameter,)) | 201 | + entry_data_process = multiprocessing.Process( |
202 | + target=EntryDataVacuate().entry, args=(parameter,)) | ||
180 | entry_data_process.start() | 203 | entry_data_process.start() |
181 | running_dict[entry_data_process] = this_task_layer | 204 | running_dict[entry_data_process] = this_task_layer |
182 | except Exception as e: | 205 | except Exception as e: |
@@ -189,4 +212,4 @@ def data_entry_center(): | @@ -189,4 +212,4 @@ def data_entry_center(): | ||
189 | sys_session.commit() | 212 | sys_session.commit() |
190 | except Exception as e: | 213 | except Exception as e: |
191 | sys_session.commit() | 214 | sys_session.commit() |
192 | - StructurePrint.print(e.__str__(),"error") | ||
215 | + StructurePrint.print(e.__str__(), "error") |
app/modules/auth/__init__.py
0 → 100644
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)) |
app/modules/auth/models/__init__.py
0 → 100644
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') |
app/modules/auth/oauth2.py
0 → 100644
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()) |
app/templates/auth/authorize.html
0 → 100644
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> |
app/templates/auth/create_client.html
0 → 100644
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> |
app/templates/auth/login.html
0 → 100644
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 | ||
2 | -SQLAlchemy==1.3.17 | ||
3 | -Flask-SQLAlchemy==2.4.3 | ||
4 | -gevent==20.9.0 | ||
5 | -gunicorn==20.0.4 | ||
6 | -flask_cors==3.0.8 | ||
7 | -flasgger==0.9.5 | ||
8 | -GDAL==3.2.1 | ||
9 | -psycopg2==2.8.5 | ||
10 | -pyDes==2.0.1 | ||
11 | -gevent-websocket==0.10.1 | ||
12 | -Pillow==8.1.2 | ||
13 | -#Rtree==0.9.7 | ||
14 | -opencv-python==4.5.1.48 | ||
15 | -psutil==5.8.0 | ||
16 | -mod_wsgi==4.8.0 | ||
1 | +flask==1.1.2 | ||
2 | +SQLAlchemy==1.3.17 | ||
3 | +Flask-SQLAlchemy==2.4.3 | ||
4 | +gevent==20.9.0 | ||
5 | +gunicorn==20.0.4 | ||
6 | +flask_cors==3.0.8 | ||
7 | +flasgger==0.9.5 | ||
8 | +GDAL==3.2.1 | ||
9 | +psycopg2==2.8.5 | ||
10 | +pyDes==2.0.1 | ||
11 | +gevent-websocket==0.10.1 | ||
12 | +Pillow==8.1.2 | ||
13 | +#Rtree==0.9.7 | ||
14 | +opencv-python==4.5.1.48 | ||
15 | +pstuil==5.8.0 | ||
16 | +mod_wsgi==4.8.0 | ||
17 | +Authlib==0.13 | ||
18 | + |
@@ -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) |
请
注册
或
登录
后发表评论