Skip to content

Path auth

English | 中文

HTTP / gRPC middleware uses PathAuthConfig to decide which paths require login. Allow anonymous routes with excludedo not rely on #[sa_ignore] (it only skips macro checks).

When to use

  • Default auth for the whole app, with a few public paths (/login, /health).
  • Split duties: middleware answers “logged in?”, macros answer “has permission / role?”.

PathAuthConfig

rust
use sa_token_core::router::PathAuthConfig;

let config = PathAuthConfig::new()
    .include(vec!["/**".into()])           // paths that require auth (Ant-style)
    .exclude(vec![
        "/api/login".into(),
        "/health".into(),
        "/public/**".into(),
    ])
    .validator(|login_id| {                 // optional extra login_id check
        !login_id.is_empty()
    });

Rule: need_auth = matches include AND does not match exclude.

PatternMeaning
/**All paths
/api/**Prefix /api
/api/*One segment under /api (/api/user yes, /api/a/b no)
*.htmlEnds with .html
/exactExact match

run_auth_flow

Framework layers share one pipeline:

text
extract_token_from(req, config)
  → process_auth(path, token, PathAuthConfig?, manager)
  → create_context → AuthFlowResult
rust
use sa_token_core::router::run_auth_flow;

// Some(config): include/exclude may produce 401
// None: validate token if present; never reject by path
let flow = run_auth_flow(&adapter, &manager, Some(&config)).await;
if flow.should_reject() {
    // binding returns 401
}

AuthFlowResult::run(fut) runs the handler inside SaTokenContext::scope so StpUtil parameterless APIs work.

Layer: with_path_auth vs macros

Axum:

rust
use sa_token_plugin_axum::{SaTokenLayer, SaTokenState};
use sa_token_core::PathAuthConfig;

let state = SaTokenState::builder()
    .storage(storage)
    .build();

let path = PathAuthConfig::new()
    .include(vec!["/**".into()])
    .exclude(vec!["/api/login".into()]);

let app = axum::Router::new()
    .route("/api/login", /* ... */)
    .route("/api/user", /* ... */)
    .layer(SaTokenLayer::with_path_auth(state.clone(), path));

Actix:

rust
use sa_token_plugin_actix_web::{PathAuthConfig, SaTokenMiddleware};

App::new().wrap(SaTokenMiddleware::with_path_auth(
    state.clone(),
    PathAuthConfig::new()
        .include(vec!["/**".into()])
        .exclude(vec!["/api/login".into()]),
))
MechanismDoesDoes not
SaTokenLayer::with_path_auth / SaTokenMiddleware::with_path_authPath-level login gate; fills contextCheck permission strings
#[sa_check_login] / #[sa_check_permission]Fine-grained checks in the handlerBypass middleware
#[sa_ignore]Skip inserting macro checksSkip the Layer

SaTokenLayer::new(state) without path config only validates a present token and fills context — anonymous requests pass. Use that when routes protect themselves with macros.

Pitfalls

  1. Forgetting to exclude login → clients always get 401.
  2. Only #[sa_ignore] without exclude → middleware still rejects.
  3. Empty include → no path ever need_auth (path enforcement off).

MIT OR Apache-2.0