Superset 用戶集成完整方案(iframe方式)


本次集成方案經過個人測試,根據前面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>

恭喜你,到此為止,用戶集成問題,解決完畢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM