Path-Based Authentication Guide
中文 | English
Overview
Path-based authentication allows you to configure which routes require authentication and which are excluded, providing fine-grained control over access without modifying individual route handlers.
Table of Contents
Quick Start
Dependencies (0.1.14): use sa-token-plugin-actix-web with default v4 + memory for Actix-web (see Quick Start).
Basic Usage
rust
use sa_token_core::router::PathAuthConfig;
use sa_token_plugin_actix_web::{SaTokenMiddleware, SaTokenState, MemoryStorage};
use std::sync::Arc;
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.build();
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string(), "/api/health".to_string()]);
App::new()
.wrap(SaTokenMiddleware::with_path_auth(state, config))Configuration
PathAuthConfig
The PathAuthConfig struct provides a builder pattern for configuring path authentication:
rust
let config = PathAuthConfig::new()
.include(vec![
"/api/**".to_string(),
"/admin/**".to_string(),
])
.exclude(vec![
"/api/public/**".to_string(),
"/api/login".to_string(),
])
.validator(|login_id| {
// Custom validation logic
login_id.starts_with("user_")
});Methods
include(patterns): Set paths that require authenticationexclude(patterns): Set paths excluded from authenticationvalidator(fn): Set custom login ID validator function
Pattern Matching
Supported Patterns
| Pattern | Description | Example |
|---|---|---|
/** | Match all paths | Matches everything |
/api/** | Multi-level prefix match | Matches /api/user, /api/user/profile |
/api/* | Single-level prefix match | Matches /api/user, not /api/user/profile |
*.html | Suffix match | Matches /page.html |
/exact | Exact match | Only matches /exact |
Matching Rules
- Include patterns are checked first - if path matches, authentication is required
- Exclude patterns override include patterns - if path matches exclude, authentication is not required
- If no include patterns are set, no paths require authentication
- If path matches neither include nor exclude, authentication is not required
Examples
Example 1: Protect API Routes
rust
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
// /api/user -> requires auth
// /api/public/info -> no auth required
// /web/page -> no auth requiredExample 2: Multiple Include Patterns
rust
let config = PathAuthConfig::new()
.include(vec![
"/api/**".to_string(),
"/admin/**".to_string(),
])
.exclude(vec![
"/api/login".to_string(),
"/api/register".to_string(),
]);Example 3: Custom Validator
rust
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.validator(|login_id| {
// Only allow login IDs starting with "user_"
login_id.starts_with("user_")
});Framework Integration
Built-in with_path_auth examples follow for Actix-web, Axum, Poem, Salvo, Ntex, and Tide. Rocket, Gotham, and Warp provide global auth layers first — combine PathAuthConfig in handlers or macros when you need path rules (full guide).
Actix-web
rust
use sa_token_plugin_actix_web::{SaTokenMiddleware, PathAuthConfig};
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
App::new()
.wrap(SaTokenMiddleware::with_path_auth(state, config))Axum
rust
use sa_token_plugin_axum::{SaTokenLayer, PathAuthConfig};
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
Router::new()
.layer(SaTokenLayer::with_path_auth(state, config))Poem
rust
use sa_token_plugin_poem::{SaTokenLayer, PathAuthConfig};
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
Route::new()
.with(SaTokenLayer::with_path_auth(state, config))Salvo
rust
use sa_token_plugin_salvo::{SaTokenLayer, PathAuthConfig};
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
Router::new()
.hoop(SaTokenLayer::with_path_auth(state, config))Ntex
rust
use sa_token_plugin_ntex::{SaTokenLayer, PathAuthConfig};
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
App::new()
.wrap(SaTokenLayer::with_path_auth(state, config))
// ...routesTide
rust
use sa_token_plugin_tide::{SaTokenLayer, PathAuthConfig};
let config = PathAuthConfig::new()
.include(vec!["/api/**".to_string()])
.exclude(vec!["/api/public/**".to_string()]);
app.with(SaTokenLayer::with_path_auth(state, config))Best Practices
- Use specific patterns: Prefer
/api/user/*over/api/**when possible - Exclude public routes: Always exclude login, register, and public API routes
- Test patterns: Verify your patterns match expected paths
- Use validators: Add custom validation for additional security
- Document patterns: Keep a list of protected and public routes
API Reference
PathAuthConfig
rust
impl PathAuthConfig {
pub fn new() -> Self;
pub fn include(self, patterns: Vec<String>) -> Self;
pub fn exclude(self, patterns: Vec<String>) -> Self;
pub fn validator<F>(self, f: F) -> Self
where
F: Fn(&str) -> bool + Send + Sync + 'static;
pub fn check(&self, path: &str) -> bool;
pub fn validate_login_id(&self, login_id: &str) -> bool;
}Helper Functions
rust
pub fn match_path(path: &str, pattern: &str) -> bool;
pub fn match_any(path: &str, patterns: &[&str]) -> bool;
pub fn need_auth(path: &str, include: &[&str], exclude: &[&str]) -> bool;
pub fn extract_token<R: SaRequest>(req: &R, token_name: &str) -> Option<String>;
pub async fn run_auth_flow<R: SaRequest>(req: &R, manager: &SaTokenManager, config: Option<&PathAuthConfig>) -> AuthFlowResult;AuthFlowResult
rust
impl AuthFlowResult {
// true if binding should respond 401 (path requires auth, token missing/invalid)
pub fn should_reject(&self) -> bool;
// Run future with this flow's SaTokenContext (await-safe)
pub async fn run<F, R>(self, fut: F) -> R;
}