如何为Panel应用实现认证?避免其被通过URL直接访问
Absolutely! Securing your Panel app against direct URL access is totally doable, and there are a few solid approaches to implement token-based or session-based authentication—let’s dive into them:
1. Request Header Token Validation
This is a straightforward method for validating machine-to-machine requests, where every incoming request must include a valid token in its headers.
You can implement this using Panel's middleware feature when starting your app with pn.serve():
import panel as pn from starlette.middleware.base import BaseHTTPMiddleware from starlette.responses import PlainTextResponse # Your secret token (store this securely, e.g., environment variable) VALID_TOKEN = "your_secure_token_here" class TokenAuthMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): # Check for the auth token in request headers auth_token = request.headers.get("X-Auth-Token") if auth_token != VALID_TOKEN: return PlainTextResponse("Unauthorized", status_code=403) # Proceed to the app if token is valid response = await call_next(request) return response # Your Panel app that hosts Jupyter Notebooks (example placeholder) def notebook_host_app(): # Replace with your actual notebook hosting logic return pn.pane.Markdown("Jupyter Notebook Hosted Here") # Serve the app with the authentication middleware pn.serve( notebook_host_app, middleware=[TokenAuthMiddleware], port=5006 )
Now, only requests that include the header X-Auth-Token: your_secure_token_here will be allowed access.
2. Session-Based Login Form (For Human Users)
If you need to authenticate human users instead of just service calls, a login form with session management works well. You can use Panel's state cache to track authenticated sessions:
import panel as pn # Store valid credentials (again, use environment variables in production) VALID_CREDENTIALS = {"user1": "pass123", "admin": "securepass"} pn.extension() def check_credentials(username, password): return VALID_CREDENTIALS.get(username) == password def login_form(): username_input = pn.widgets.TextInput(name="Username") password_input = pn.widgets.PasswordInput(name="Password") submit_btn = pn.widgets.Button(name="Login", button_type="primary") error_msg = pn.pane.Alert("", alert_type="danger", visible=False) def on_login_click(event): if check_credentials(username_input.value, password_input.value): # Mark session as authenticated pn.state.cache["authenticated"] = True # Redirect to the notebook host app pn.state.location.href = "/notebook-host" else: error_msg.value = "Invalid username or password" error_msg.visible = True submit_btn.on_click(on_login_click) return pn.Column(username_input, password_input, submit_btn, error_msg) def notebook_host_app(): # Check if user is authenticated before rendering if not pn.state.cache.get("authenticated", False): return pn.pane.Alert("Please log in first!", alert_type="warning") # Your actual notebook hosting logic here return pn.pane.Markdown("Welcome! Jupyter Notebook is hosted here.") # Set up routes: login page and protected notebook page pn.serve( {"/": login_form, "/notebook-host": notebook_host_app}, port=5006 )
This will redirect unauthenticated users to the login page, and only let them access the notebook host after successful login.
3. Reverse Proxy Authentication (No App Code Changes)
If you prefer not to modify your Panel app code, you can add authentication at the reverse proxy level (e.g., Nginx). Here’s an example Nginx config snippet that checks for a valid header token:
server { listen 80; server_name your-panel-app-domain.com; location / { # Check for the auth token in headers if ($http_x_auth_token != "your_secure_token_here") { return 403; } # Proxy requests to your Panel app proxy_pass http://localhost:5006; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
This way, Nginx blocks all requests without the valid token before they even reach your Panel app.
Key Notes for Jupyter Notebook Hosting
- If your Panel app interacts with the Jupyter Notebook server directly, ensure that the authentication also covers those interactions (e.g., pass the token to the Notebook API calls if needed).
- Always store secrets like tokens or credentials in environment variables (never hardcode them in your app).
内容的提问来源于stack exchange,提问作者Mehmood

