开干
这个标题挺有意思——“选择性”,那也就是说,业务上要只对部分接口做鉴权,而上篇在 CustomSecurityManager 中做的修改则是针对接口全局的修改,在这个需求面前经不住考究。
在“最小改动”和“支持扩展”、“方便维护”原则下,肯定是要继续读源码的。
假设我现在是需要做iframe中链接的鉴权,那相关的接口就是/explore和/explore_json,我的做法也相对明确——通过装饰器实现。
首先先了解下闭包和装饰器。推荐看:https://www.cnblogs.com/linxiyue/p/11224322.html
一个典型的装饰器如下:
def deco(func):
def new_func(*args, **kwargs):
return func(*args, **kwargs)
return new_func
我们需要在调用原接口处理逻辑之前,先进行我们的验证——具体操作就是把我们的装饰器@到/explore上,当判断到是在加载iframe内容时,装饰器发生作用。
同理地,我们看一段权限校验的源码👇
def has_access(f):
if hasattr(f, '_permission_name'):
permission_str = f._permission_name
else:
permission_str = f.__name__
def wraps(self, *args, **kwargs):
permission_str = PERMISSION_PREFIX + f._permission_name
if self.appbuilder.sm.has_access(permission_str, self.__class__.__name__):
return f(self, *args, **kwargs)
else:
log.warning(LOGMSG_ERR_SEC_ACCESS_DENIED.format(permission_str, self.__class__.__name__))
flash(as_unicode(FLAMSG_ERR_SEC_ACCESS_DENIED), "danger")
return redirect(url_for(self.appbuilder.sm.auth_view.__class__.__name__ + ".login"))
f._permission_name = permission_str
return functools.update_wrapper(wraps, f)
最终我们的装饰器函数如下👇
def has_iframe_access(f):
def wraps(self, *args, **kwargs):
authorization = request.headers.get("Authorization")
v = request.args.get("standalone")
if request.method == "GET" and v == "true":
if authorization:
token = authorization.split(" ")[1]
payload = auth.verify_jwt(token)
if type(payload) == dict:
return f(self, *args, **kwargs)
else:
response = make_response(jsonify({'message': "token expired"}), 401)
response.headers['Content-Type'] = "application/json"
return response
else:
response = make_response(jsonify({'message': "access denied"}), 401)
response.headers['Content-Type'] = "application/json"
return response
else:
return f(self, *args, **kwargs)
return functools.update_wrapper(wraps, f)
先解决如何匿名访问iframe上的数据,记得在界面上操作一下用户角色权限(再次操作时我忘了,找了好久):https://blog.csdn.net/a303944689/article/details/78739269
你会发现当我们把装饰器给/explore接口加上的时候,如果没有根据协议来携带参数访问,在浏览器中访问如下链接时
http://127.0.0.1:9000/superset/explore/?form_data={"slice_id":2216}&standalone=true&height=400
服务器直接拒绝掉了,甚至都还没把后面的两个参数给去掉。
把参数加上后,即可。
网友评论