class ConsulService(object): """Consul服务, 接收服务名称, 返回域名""" def __init__(self): self.settings_value = GetSettingsValue() self.consul = self.settings_value.get_middleware_value('PERMISSION_MIDDLEWARE', 'CONSUL') self.run_env = self.settings_value.get_settings_value('RUN_ENV') def get_service_addr_consul(self, service, schema=""): """ 获取服务的consul地址 优先环境变量,如未配置环境变量,从consul中找服务, 如果是("dev", "unit"), 则使用127.0.0.1 """ port = self.settings_value.get_middleware_service_value('PERMISSION_MIDDLEWARE', service, 'port') host = self.settings_value.get_middleware_value_not_validated('PERMISSION_MIDDLEWARE', service, 'host') service_name = self.settings_value.get_middleware_service_value('PERMISSION_MIDDLEWARE', service, 'name') consul_client = consul.Consul(host=self.consul['host'], port=self.consul['port'], scheme="http") if self.run_env in ("dev", "unit"): logger.info("run_env=%s, 使用本地地址") address = '127.0.0.1' domain = "{schema}{address}:{port}".format(schema=schema, address=address, port=port) return domain if host and port: domain = "{schema}{address}:{port}".format(schema=schema, address=host, port=port) logger.info("domain={domain}".format(domain=domain)) return domain try: port = consul_client.catalog.service(service_name)[1][0]['ServicePort'] address = consul_client.catalog.service(service_name)[1][0]['ServiceAddress'] domain = "{schema}{address}:{port}".format(schema=schema, address=address, port=port) return domain except Exception: raise ImproperlyConfigured("请检查settings.py 的consul配置是否正确")
class PermissionMiddleware(permissions.BasePermission): """ 权限中间件 使用方法: 1.导入此文件到项目中 2.将此中间件放在 AuthenticationMiddleware 之后 工作原理: (url + method + user_id) | / 有权限则允许通过 request -> PermissionMiddleware ---https---> 权限模块 \ 无权限则返回HTTP 403错误 """ VERIFICATION_CONGIGURATION = VerificationConfiguration() VERIFICATION_CONGIGURATION.valid_permission_svc() SETTINGS_VALUE = GetSettingsValue() URL_JOIN = NormalizeUrl() FILTER_PATH = SETTINGS_VALUE.get_middleware_value( 'PERMISSION_MIDDLEWARE', 'FILTER_PATH') SERVICE_NAME = SETTINGS_VALUE.get_middleware_service_value( 'PERMISSION_MIDDLEWARE', 'PERMISSION_SERVICE', 'name') PERMISSION_ADDRESS = SETTINGS_VALUE.get_middleware_service_value( 'PERMISSION_MIDDLEWARE', 'PERMISSION_SERVICE', 'address') HAS_PERMISSION = True def has_permission(self, request, view): # 验证中间件位置 self.VERIFICATION_CONGIGURATION.verify_middleware_location(request) path = request.path method = request.method.upper() # 只校验有 不在 FILTER_PATH 中的url if path not in self.FILTER_PATH: if request.user.id: self.HAS_PERMISSION = self.valid_permission(path, method, request.user.id) if self.HAS_PERMISSION: return True return False def valid_permission(self, path, method, user_id): """ 验证权限, 目前使用的是http的方式验证,后面可能要改成rpc的方式""" if all([path, method, user_id]): domain = ConsulService().get_service_addr_consul(service='PERMISSION_SERVICE') url = self.URL_JOIN.normalize_url( domain=domain, path=self.PERMISSION_ADDRESS) post_data = { "path": path, "method": method, "user_id": user_id } response = requests.post(url, json=post_data) if response.status_code == 404: raise ImproperlyConfigured( "请检查settings.py的permission_service配置的%s是否正确" % path) data = response.json() if response.status_code == 500: logger.error(data["message"]) return True if 200 <= response.status_code < 300 and data['status']: return True return False
class TestURLSplicing(unittest.TestCase): """测试url拼接""" def setUp(self): self.get_value = GetSettingsValue() self.get_value.get_settings_value = mock.Mock( return_value=PERMISSION_MIDDLEWARE) self.get_value.get_middleware_value = mock.Mock( return_value=PERMISSION_MIDDLEWARE['PERMISSION_SERVICE']) def test_get_middleware_value(self): service_value = self.get_value.get_settings_value( 'PERMISSION_MIDDLEWARE') value = service_value.get('PERMISSION_SERVICE', None) self.assertEqual(value, PERMISSION_MIDDLEWARE['PERMISSION_SERVICE']) def test_get_middleware_service_value(self): middleware_value = self.get_value.get_middleware_value() value = middleware_value.get('name', None) self.assertEqual(value, PERMISSION_MIDDLEWARE['PERMISSION_SERVICE']['name'])
class DecodeJwt(object): """decode_jwt""" def __init__(self, ): self.settings_value = GetSettingsValue() self.secret = self.settings_value.get_middleware_value( 'JWT_AUTHENTICATION_MIDDLEWARE', 'JWT_SECRET') def decode_jwt(self, token): secret = self.secret try: payload = jwt.decode(token, secret, algorithms='HS256') except Exception as ex: raise ex return payload
from sparrow_django_common.utils.get_settings_value import GetSettingsValue from sparrow_django_common.base_middlware.base_middleware import MiddlewareMixin get_value = GetSettingsValue() METHOD_MAP = get_value.get_middleware_value('METHOD_MIDDLEWARE', 'METHOD_MAP') if not METHOD_MAP: METHOD_MAP = ('PUT', 'DELETE') class MethodConvertMiddleware(MiddlewareMixin): """解决阿里云不支持put/delete 请求方式的问题""" def process_request(self, request): if 'HTTP_METHOD' in request.META: method = request.META['HTTP_METHOD'].upper() if method in METHOD_MAP: setattr(request, 'method', method)
def __init__(self, ): self.settings_value = GetSettingsValue() self.secret = self.settings_value.get_middleware_value( 'JWT_AUTHENTICATION_MIDDLEWARE', 'JWT_SECRET')
def __init__(self): self.settings_value = GetSettingsValue() self.run_env = self.settings_value.get_settings_value('RUN_ENV')
def get_settings_value(): """Get the data in settings and add value validation""" settings_value = GetSettingsValue() user_class_path = settings_value.get_middleware_value( JWT_AUTHENTICATION_MIDDLEWARE, USER_CLASS_PATH) return user_class_path
class PermissionMiddleware(permissions.BasePermission): """ 权限中间件 使用方法: 1.导入此文件到项目中 2.将此中间件放在 AuthenticationMiddleware 之后 工作原理: (url + method + user_id) | / 有权限则允许通过 request -> PermissionMiddleware ---https---> 权限模块 \ 无权限则返回HTTP 403错误 """ VERIFICATION_CONGIGURATION = VerificationConfiguration() VERIFICATION_CONGIGURATION.valid_permission_svc() SETTINGS_VALUE = GetSettingsValue() URL_JOIN = NormalizeUrl() FILTER_PATH = SETTINGS_VALUE.get_middleware_value('PERMISSION_MIDDLEWARE', 'FILTER_PATH') SERVICE_NAME = SETTINGS_VALUE.get_middleware_service_value( 'PERMISSION_MIDDLEWARE', 'PERMISSION_SERVICE', 'name') PERMISSION_ADDRESS = SETTINGS_VALUE.get_middleware_service_value( 'PERMISSION_MIDDLEWARE', 'PERMISSION_SERVICE', 'address') HAS_PERMISSION = False def has_permission(self, request, view): # 验证中间件位置 path = request.path method = request.method.upper() url = request.META.get('HTTP_REFERER', None) # 只校验有 不在 FILTER_PATH 中的url if path not in self.FILTER_PATH: if request.user: try: if request.user.is_authenticated(): self.HAS_PERMISSION = self.valid_permission( path, method, request.user.id) except: if request.user.is_authenticated: self.HAS_PERMISSION = self.valid_permission( path, method, request.user.id) if self.HAS_PERMISSION: return True return False elif url is not None: if url.__contains__("login"): return True return False return True def valid_permission(self, path, method, user_id): """ 验证权限, 目前使用的是http的方式验证,后面可能要改成rpc的方式""" if all([path, method, user_id]): domain = ConsulService().get_service_addr_consul( service_dependencies='PERMISSION_MIDDLEWARE', service='PERMISSION_SERVICE') url_path = self.URL_JOIN.normalize_url( domain=domain, path=self.PERMISSION_ADDRESS) url = url_path + '?userid={0}&path={1}&method={2}'.format( user_id, path, method) try: response = requests.get(url) except Exception as ex: logger.error(ex) return True if response.status_code == 404: raise ImproperlyConfigured( "请检查settings.py的permission_service配置的%s是否正确" % self.PERMISSION_ADDRESS) data = response.json() if response.status_code == 500: logger.error(data["message"]) return True if 200 <= response.status_code < 300 and data['status']: return True return False
def setUp(self): self.get_value = GetSettingsValue() self.get_value.get_settings_value = mock.Mock( return_value=PERMISSION_MIDDLEWARE) self.get_value.get_middleware_value = mock.Mock( return_value=PERMISSION_MIDDLEWARE['PERMISSION_SERVICE'])
def __init__(self): self.settings_value = GetSettingsValue() self.consul = self.settings_value.get_middleware_value('PERMISSION_MIDDLEWARE', 'CONSUL') self.run_env = self.settings_value.get_settings_value('RUN_ENV')
class PermissionMiddleware(MiddlewareMixin): """ 权限中间件 使用方法: 1.导入此文件到项目中 2.将此中间件放在 AuthenticationMiddleware 之后 工作原理: (url + method + user_id) | / 有权限则允许通过 request -> PermissionMiddleware ---https---> 权限模块 \ 无权限则返回HTTP 403错误 """ VERIFICATION_CONGIGURATION = VerificationConfiguration() VERIFICATION_CONGIGURATION.valid_permission_svc() SETTINGS_VALUE = GetSettingsValue() URL_JOIN = NormalizeUrl() FILTER_PATH = SETTINGS_VALUE.get_middleware_value('PERMISSION_MIDDLEWARE', 'FILTER_PATH') SERVICE_NAME = SETTINGS_VALUE.get_middleware_service_value( 'PERMISSION_MIDDLEWARE', 'PERMISSION_SERVICE', 'name') PERMISSION_ADDRESS = SETTINGS_VALUE.get_middleware_service_value( 'PERMISSION_MIDDLEWARE', 'PERMISSION_SERVICE', 'address') HAS_PERMISSION = True SKIP_PERMISSION = SETTINGS_VALUE.get_value('PERMISSION_MIDDLEWARE', 'SKIP_PERMISSION') def process_request(self, request): # 验证中间件位置 path = request.path method = request.method.upper() # 只校验有 不在 FILTER_PATH 中的url if self.SKIP_PERMISSION is False or self.SKIP_PERMISSION == 'False': if path not in self.FILTER_PATH: if request.META['REMOTE_USER']: self.HAS_PERMISSION = self.valid_permission( path, method, request.META['REMOTE_USER']) if not self.HAS_PERMISSION: return JsonResponse({"message": "无访问权限"}, status=403) def valid_permission(self, path, method, user_id): """ 验证权限, 目前使用的是http的方式验证,后面可能要改成rpc的方式""" if all([path, method, user_id]): domain = ConsulService().get_service_addr_consul( service_dependencies='PERMISSION_MIDDLEWARE', service='PERMISSION_SERVICE') url_path = self.URL_JOIN.normalize_url( domain=domain, path=self.PERMISSION_ADDRESS) url = url_path + '?userid={0}&path={1}&method={2}'.format( user_id, path, method) try: response = requests.get(url) except Exception as ex: logger.error(ex) return True if response.status_code == 404: raise ImproperlyConfigured( "请检查settings.py的permission_service配置的%s是否正确" % self.PERMISSION_ADDRESS) data = response.json() if response.status_code == 500: logger.error(data["message"]) return True if 200 <= response.status_code < 300 and data['status']: return True return False