正在显示
11 个修改的文件
包含
452 行增加
和
41 行删除
@@ -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") |
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 | 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) |
请
注册
或
登录
后发表评论