开干
继承关系:
SupersetSecurityManager->SecurityManager->BaseSecurityManager->AbstractSecurityManager->BaseManager
其中除了第一个,其他的类已经是在flask_appbuilder范畴,可见是基于flask_appbuilder。
__init__.py中
custom_sm = app.config.get('CUSTOM_SECURITY_MANAGER') or SupersetSecurityManager
if not issubclass(custom_sm, SupersetSecurityManager):
raise Exception(
"""Your CUSTOM_SECURITY_MANAGER must now extend SupersetSecurityManager,
not FAB's security manager.
See [4565] in UPDATING.md""")
appbuilder = AppBuilder(
app,
db.session,
base_template='superset/base.html',
indexview=MyIndexView,
security_manager_class=custom_sm,
update_perms=utils.get_update_perms_flag(),
)
如果没有传入security_manager_class参数,appbuilder将会使用from flask_appbuilder.security.sqla.manager import SecurityManager(即SupersetSecurityManager的父类)作为security_manager。
所有配置基本都在BaseSecurityManager类中,
...
def __init__(self, appbuilder):
super(BaseSecurityManager, self).__init__(appbuilder)
app = self.appbuilder.get_app
...
authdbview = AuthDBView
""" Override if you want your own Authentication DB view """
并且通过flask_appbuilder提供的方法获取配置类型的方法
def auth_type(self):
return self.appbuilder.get_app.config['AUTH_TYPE']
找到superset项目的config.py文件中,
from flask_appbuilder.security.manager import AUTH_DB
...
AUTH_TYPE = AUTH_DB
因此,默认的鉴权方式是AUTH_DB,flask_appbuilder的base.py中appbuilder类下
...
@property
def get_url_for_login(self):
return url_for("%s.%s" % (self.sm.auth_view.endpoint, "login"))
@property
def get_url_for_logout(self):
return url_for("%s.%s" % (self.sm.auth_view.endpoint, "logout"))
...
可见使用AUTH_TYPE指定的鉴权方式对登入登出进行校验。
BaseView类中
...
# If endpoint name is not provided, get it from the class name
self.endpoint = endpoint or self.__class__.__name__
...
鉴权
现在来看看appbuilder内对登录的鉴权逻辑,
class AuthDBView(AuthView):
login_template = 'appbuilder/general/security/login_db.html'
@expose('/login/', methods=['GET', 'POST'])
def login(self):
if g.user is not None and g.user.is_authenticated():
return redirect(self.appbuilder.get_url_for_index)
form = LoginForm_db()
if form.validate_on_submit():
# 调用 auth_user_db 验证,内部调用 check_password_hash
# 比对表单中的password和数据库的哈希值是否匹配
user = self.appbuilder.sm.auth_user_db(form.username.data, form.password.data)
if not user:
flash(as_unicode(self.invalid_login_message), 'warning')
return redirect(self.appbuilder.get_url_for_login)
# 验证通过调用login_user生成认证信息
login_user(user, remember=False)
return redirect(self.appbuilder.get_url_for_index)
return self.render_template(self.login_template,
title=self.title,
form=form,
appbuilder=self.appbuilder)
iframe集成superset
- superset基本设置
!!先登录后鉴权,登录和鉴权是分离的!!
将PUBLIC_ROLE_LIKE_GAMMA设置为True,并给public角色增加can explore on Superset, can explore json on Superset, all database access on all_database_access三种权限,最后一种看你需要。这种方式会将所有请求视为来自最高权限用户,本质其实就是【无登录有鉴权】,但也仅针对iframe或者chart表详情页无需登录,即可拥有public的权限。
需要关联(设置为Ture)才能使页面上对public角色的权限配置生效
为了明确,这里展示了我这边public现有配置的权限👇
- 如果一个web应用想要集成superset的图表,且要求数据接口仅对特定应用开放,那就需要修改鉴权方式,将原来通过提交用户名和密码的鉴权方式替换为自己的应用认证方式。
方式如下:
2.1 继承AuthDBView类,重写login方法,大致逻辑如下:从链接中获取token->对token鉴权->成功或失败跳转(携带参数);
2.2 继承SupersetSecurityManager类,将AuthDBView子类赋值给authdbview;
2.3 修改config文件,将SupersetSecurityManager子类赋值给CUSTOM_SECURITY_MANAGER。
** 鉴权类的接口我认为都可以放在这个视图下面。