本次集成方案經過個人測試,根據前面2個集成方案的資料,撰寫,相關說明由於個人知識水平有限不一定理解准確,有錯誤的地方環境評論區評論;
1、用戶集成方式:
- A系統用戶,通過A的某個界面,iframe嵌入
- superset接到用戶信息后,在superset系統中查找用戶,如果用戶存在,則登錄,並形成session,如果用戶不存在則新增用戶,當然如果用戶角色發生變化,則更新用戶,並redirect 目標地址
- 用戶建立后,如何實現行權限設置,顯示用戶授權的數據?我這里通過建立動態查詢語句實現。
- 嵌入后去除嵌入的dashboard的頁面頭
2、前期准備,參數設置:Superset config配置文件參數,里面的 跨域訪問問題 sql中使用參數問題 設置好;
3、具體細節:
(1)iframe問題:
測試用的鏈接地址如下:http://superset.alibaba.com:9001/login/?username=jiamidadao&userrole=public&redirect=http://iframe.alibaba.com:9001/superset/dashboard/11/
這里會遇到iframe 跟 redirect 后,session丟失問題
這里我個人理解,沒有完全理論知識,跨域訪問中,使用了iframe會出現session丟失問題,其實也不是丟失,因為iframe框架返回的session,不是iframe嵌入的鏈接目標網站的session,而是主站(比如A系統,嵌入superet dashboard頁面,A系統是主站)的session,所以用戶集成的第2部分iframe的superset網站訪問后,用戶登錄成功,返回session是正確返回的,但是當redirect命令到的時候,瀏覽器執行location重定向,瀏覽器判斷當前系統沒有目標網站 http://iframe.alibaba.com:9001/superset/dashboard/11/ 的session(由於登錄的session屬於主站),所以不會帶着前面登錄的session,導致登錄不成功,又再次返回登錄界面,當然如果此時打印g.user會返回匿名用戶,所以這里必須解決iframe 的 session 通用性問題:
針對這個問題解決方法如下:A系統即主站系統的域名設置為:main.alibaba.com ; superset系統域名設置為 superset.alibaba.com ;
在superset的配置文件config.py里面設置 SESSION_COOKIE_DOMAIN = ".alibaba.com"
這樣設置后,superset登錄環境返回的session就會被瀏覽器再次調用,iframe的redirect 后session問題解決
如果你還有其他方式,請留言;
此處衍生下,在開發環節,沒有域名做解析,怎么辦?
通過在客戶機上設置host 做域名劫持,進而實現:
127.0.0.1 superset.alibaba.com main.alibaba.com
同時,本機上安裝代理服務器,比如Apache Tomcat 8.5 Tomcat8 ,安裝后,啟動,將下面文件放到根目錄,命名為aa.html,
<html> <head> <title>dashboard</title> <style type="text/css"> .dashboard { width: 100%; margin: 0 auto; } .dashboard iframe { width: 100%; height: 100%; margin-top: -150px; } </style> </head> <body> <div class="dashboard"> <div class="superset-legacy-chart-nvd3 superset-legacy-chart-nvd3-dist-bar"> <iframe src='http://superset.alibaba.com:9001/login/?username=jiamiyonghu&userrole=public&redirect=http://superset.alibaba.com:9001/superset/dashboard/11/'> </iframe> </div> </div> </body> <script> </script> </html>
然后瀏覽器訪問:http://main.alibaba.com:8080/aa.html
當然訪問前,必須要superset啟動程序要打開,比如啟動后監聽的端口號為9001,本地運行;
下面解決第2步:
(2)用戶集成代碼
在superset目錄下,跟config.py一個目錄,新建pthon文件,security1.py
from flask import redirect, g, flash, request from flask_appbuilder.security.views import UserDBModelView,AuthDBView from superset.security import SupersetSecurityManager from flask_appbuilder.security.views import expose from flask_appbuilder.security.manager import BaseSecurityManager from flask_login import login_user, logout_user class CustomAuthDBView(AuthDBView): login_template = 'appbuilder/general/security/login_db.html' @expose('/login/', methods=['GET', 'POST']) def login(self): redirect_url = self.appbuilder.get_url_for_index if request.args.get('redirect') is not None: redirect_url = request.args.get('redirect') if request.args.get('username') is not None: user = self.appbuilder.sm.find_user(username=request.args.get('username')) login_user(user, remember=False) return redirect(redirect_url) elif g.user is not None and g.user.is_authenticated(): #注意經過測試,g.user.is_authenticated()似乎不應當加() return redirect(redirect_url) else: flash('Unable to auto login', 'warning') return super(CustomAuthDBView,self).login() class CustomSecurityManager(SupersetSecurityManager): authdbview = CustomAuthDBView def __init__(self, appbuilder): super(CustomSecurityManager, self).__init__(appbuilder)
注意,上面代碼只實現了簡單的查找用戶,可以自己再完善下,比如新增,和更新,並且驗證密碼,同時主站傳過來的可以時token加密的,這里做解密等,都在上面代碼里面修改;
在config.py文件里面新增兩行代碼
from security import CustomSecurityManager CUSTOM_SECURITY_MANAGER = CustomSecurityManager
執行superset init,重啟superset系統,權限完成;提醒下,注意第2步中的參數修改問題;
上述security1的代碼另外一個參考是
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自動添加用戶,但是增加的是admin,可以改為增加public或者其他角色,訪問的時候直接訪問:http://superset.alibaba.com:9001/login/?token=jwt_token&redirect=http://superset.alibaba.com:9001/superset/dashboard/11/ 即可
(3)實現用戶行權限設置,根據用戶在主站的授權,顯示對應數據
- A系統數據庫建立數據權限驗證數據庫,數據庫內容就是用戶名,用戶名對應的事實表訪問權限關系,舉例:如果用戶是依據部門和產品線授權,則權限視圖如下:
creatview useraccess as
select 用戶名,部門,產品線 from V_用戶授權表
至於用戶授權表怎么形成,自己根據公司業務情況,自己去寫視圖;
對於dashboard中使用的數據源,在對應的在datasets中,自定義下sql語句,如:
{% if current_userrole() == 'admin' %} select a.* from sales a {% else %} select a.* from sales a inner join v_用戶權限表 b on a.部門=b.部門 and a.產品線=b.產品線 where b.用戶名='{{current_username()}}' {% endif %}
至於如何自定義參數及都有哪些參數可用,見Superset實現動態SQL查詢
(4)去除嵌入的superset的頁面頭部不需要的信息:
在主站A上,嵌入頁面的css里面寫入下面代碼:
<style type="text/css"> .dashboard { width: 100%; margin: 0 auto; } .dashboard iframe { width: 100%; height: 100%; margin-top: -150px; } </style>
恭喜你,到此為止,用戶集成問題,解決完畢