如何在 Shiny for Python 中进行 SSO 身份验证后获取当前会话详细信息?

问题描述 投票:0回答:1

我正在创建一个具有 SSO 身份验证的应用程序。身份验证完成后,我可以使用

request.session.get('user')
获取用户详细信息。 我在闪亮的服务器功能之外创建了一个变量
user_details = {}
,并将会话详细信息分配给它,它工作正常。问题是,当每个用户登录时,这些数据将保留在服务器中。当我和我的朋友完成 SSO 后登录网页时,他在他的会话中看到了我的名字。

经过一番研究,我发现我需要将

user_details
变量放在闪亮的服务器函数中,但这样做后,我无法将会话用户详细信息分配给该变量。

代码:

def server(input, output, session):
    user_details = session.user
    print(user_details)


shiny_app = App(app_ui, server)

#----------------------------------------------------------------------END OF SHINY-----------------------------------------------------

#---------------------------------------------------------------------START OF SSO-------------------------------------------------------

config = Config('.env')
oauth = OAuth()

CONF_URL = #config url

oauth.register(
    name = "app",
    server_metadata_url = CONF_URL,
    client_id  = config.get('client_id'),
    client_secret = config.get('client_secret'),
    client_kwargs={
        'scope': 'openid email'
    }
)

random_secret_key = secrets.token_urlsafe(32)

class AuthMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        # Check if the user is authenticated
        user = request.session.get("user")

        # List of paths that require authentication
        protected_paths = ["/dash", "/dash/"]

        # If the path is protected and the user is not authenticated
        if request.url.path in protected_paths and not user:
            #Redirect to the login page or SSO login flow
            return RedirectResponse(url="/login")

        # Proceed with the next middleware or route handler
        response = await call_next(request)
        return response

async def homepage(request):
    global user_details
    user =  request.session.get('user')
    if user:
        return RedirectResponse(url='/dash')
        #return JSONResponse(user)
    return RedirectResponse(url = '/login')
 
async def login(request):
    redirect_uri = request.url_for('auth') 
    return await oauth.app.authorize_redirect(request, redirect_uri)

async def auth(request):
    token = await oauth.app.authorize_access_token(request)
    user = token.get('userinfo')
    if user:
        request.session['user'] = user
    return RedirectResponse(url='/')

async def healthcheck(request):
    return JSONResponse({"Status" : "running"}, headers = {"Cache-Control" : "max-age=0, no-cache, no-store"})

routes = [
    Route('/health/ping', healthcheck),
    Route('/', homepage),
    Route('/login', login),
    Route('/auth', auth),
    Mount('/Static', StaticFiles(directory = 'www'), name = 'static'),
    Mount('/dash', app = shiny_app)
]

app = Starlette(routes=routes)
app.add_middleware(AuthMiddleware)
app.add_middleware(SessionMiddleware, secret_key = random_secret_key)

我使用了文档中描述的

session.get_current_session()
方法,但它说“AppSession”对象没有属性
get_current_session()
方法。

python py-shiny
1个回答
0
投票

对于任何正在寻找答案的人, 将每个会话中需要独立或刷新的所有变量放在闪亮的服务器功能中。这可确保现在为登录服务器的每个用户新创建所有变量。

接下来,您需要从 cookie 中更新用户信息。到目前为止,这是我发现的最好的解决方案。当用户点击网页的根目录时,您需要读取 cookie,并且还需要从服务器的所有可能的 url 中读取 cookie 中的数据。我添加了一个单独的中间件来处理用户从“/dash”网址点击时的请求。因此,当用户从“/dash”url 访问我的网页时,我的中间件将读取 cookie 中的数据并将其加载到会话中。我认为有比向服务器中所有可能的 url 添加中间件更好的解决方案。但就目前而言,这个方法对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.