superset 認證分析
superset基於flask-appbuilder開發,security基於flask_appbuilder.security,翻閱其代碼,
找到入口: superset/__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=get_update_perms_flag(), ) security_manager = appbuilder.sm
默認使用SupersetSecurityManager
,繼承自SecurityManager
:
class SupersetSecurityManager(SecurityManager): def get_schema_perm(self, database, schema): if schema: return '[{}].[{}]'.format(database, schema) def can_access(self, permission_name, view_name): """Protecting from has_access failing from missing perms/view""" user = g.user if user.is_anonymous: return self.is_item_public(permission_name, view_name) return self._has_view_access(user, permission_name, view_name) ...
我們再來看SecurityManager及父類,發現,登錄是通過auth_view來控制的,默認是AUTH_DB,也就是AuthDBView。
""" Override if you want your own Authentication LDAP view """ authdbview = AuthDBView if self.auth_type == AUTH_DB: self.user_view = self.userdbmodelview self.auth_view = self.authdbview() @property def get_url_for_login(self): return url_for('%s.%s' % (self.sm.auth_view.endpoint, 'login'))
再來看authdbview:
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(): 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(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)
對外提供'/login/'接口,讀取HTTP POST里的用戶名,密碼,然后調用auth_user_db驗證,驗證通過調用login_user生成認證信息。
因此,我們可以自定義AuthDBView,改為從我們自己的應用認證即可。
使用jwt來驗證superset
自定義CustomAuthDBView,繼承自AuthDBView,登錄時可以通過cookie或者url參數傳入jwt token,然后驗證通過的話,自動登錄,。
import jwt import json class CustomAuthDBView(AuthDBView): login_template = 'appbuilder/general/security/login_db.html' @expose('/login/', methods=['GET', 'POST']) def login(self): token = request.args.get('token') if not token: token = request.cookies.get('access_token') if token is not None: jwt_payload = jwt.decode(token,'secret',algorithms=['RS256']) user_name = jwt_payload.get("user_name") user = self.appbuilder.sm.find_user(username=user_name) if not user: role_admin = self.appbuilder.sm.find_role('Admin') user = self.appbuilder.sm.add_user(user_name, user_name, 'aimind', user_name + "@aimind.com", role_admin, password = "aimind" + user_name) if user: login_user(user, remember=False) redirect_url = request.args.get('redirect') if not redirect_url: redirect_url = self.appbuilder.get_url_for_index return redirect(redirect_url) else: return super(CustomAuthDBView,self).login() else: flash('Unable to auto login', 'warning') return super(CustomAuthDBView,self).login()
如果用戶不存在,通過self.appbuilder.sm.add_user自動添加用戶。
然后再引入這個CustomAuthDBView,
class CustomSecurityManager(SupersetSecurityManager): authdbview = CustomAuthDBView
最后,再引入這個CustomSecurityManager,在superset_config.py 里增加:
from aimind_security import CustomSecurityManager CUSTOM_SECURITY_MANAGER = CustomSecurityManager
在應用里集成superset
集成就簡單了,訪問,'SUPER_SET_URL/login/?token=jwt_token' 即可,可以通過iframe無縫集成。
轉載於:https://www.cnblogs.com/xiaoqi/p/intergate-superset.html