Authentication & Resource Permissions
Estimated reading time: 6 minutes 预计阅读时间: 6 分钟Summerrs Admin authentication is built by summer-auth and summer-system together. summer-auth handles JWTs, sessions, and token validation; summer-system provides login, refresh, logout, online devices, menu permissions, and backend API resource permissions. The main app registers these related plugins:
crates/app/src/router.rs mounts the summer-system route group under /api:
summer-system/src/router/mod.rs then applies the authentication and resource-permission layers to the whole group:
A system request flows through the layers in this order:
JWT Config
Both development and production environments configure auth through [auth]:
Supported JWT algorithms are defined in summer-auth/src/config.rs: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, and EdDSA.
HMAC algorithms use jwt_secret; asymmetric algorithms use jwt_private_key and jwt_public_key pointing to PEM files. Tokens are read from headers by default. When is_read_cookie = true is enabled, cookie reading is attempted as well; cookie mode should be paired with CSRF protection.
Login And Refresh
The system login handler is in summer-system/src/router/auth.rs:
The actual request path is:
LoginDto uses #[serde(rename_all = "camelCase")], so the fields are userName and password. The response data is:
The login flow is:
- Load the user by
sys.user.user_name. - Check account status; disabled users are rejected.
- Verify the password with Argon2.
- Load role codes through
sys.user_role -> sys.role. - Load enabled Button permissions through
sys.role_menu -> sys.menu, usingauth_markas the permission code. - Call
SessionManager::loginto issue access and refresh tokens. - Write the login log asynchronously.
The refresh endpoint is public:
Refresh first parses the refresh JWT to get the user ID, reloads the latest roles and permissions from the database, then validates the Redis refresh key and rotates a new refresh token.
Access And Refresh Responsibilities
The access JWT is self-contained. AccessClaims in summer-auth/src/token/jwt.rs includes:
The refresh JWT only stores sub, typ, iat, exp, and rid. The rid maps to Redis key auth:refresh:{rid}.
Redis session keys are mainly:
When max_devices = 5, the 6th login removes the earliest logged-in device. When concurrent_login = false, a new login clears all existing devices for that user.
Public Routes
#[public] and #[no_auth] register public routes at compile time through inventory. When AuthLayer::for_group(group) starts, it merges public routes from the same group into PathAuthConfig.exclude.
System public endpoints include:
Other summer-system endpoints require login by default.
If a route macro cannot infer the public path automatically, specify it explicitly:
Handler Permission Macros
Most management handlers use declarative permission macros:
Permission codes come from auth_mark on enabled sys.menu rows with menu_type = Button. permission_matches supports:
PermBitmapPlugin loads PermissionMap from sys.menu.bit_position on startup. When a mapping exists, login compresses the permission list into the JWT pb field; when the mapping is missing, the JWT stores the permissions array. The bitmap mainly reduces token size. Wildcard matching still runs on decoded permission strings.
Backend API Resource Permissions
In addition to handler-level #[has_perm], the system provides a backend API resource-permission layer:
ResourcePermissionPlugin loads enabled sys.resource rows on startup, queries their bound Button permissions, and builds an in-memory policy. SysResourceService calls reload_policy() after resource creation, update, enable/disable, deletion, or binding changes.
The resource layer intentionally uses pragmatic rules:
- If no login session has been injected yet, it skips and lets
AuthLayeror public-route handling decide. - If a registered resource has bound action permissions, the user may pass with any one bound permission.
- If a registered resource has not yet been bound to action permissions, it is temporarily allowed so resources can be entered gradually.
- Unregistered resources are allowed by default for compatibility with older endpoints.
In production, maintain both sides: handler #[has_perm] should not be omitted casually, and sys.resource bindings should be filled in over time.
Devices And Force-Out APIs
Auth routes also provide device management:
online.rs provides the admin view of online users:
Logout, device kick, and role/permission changes all use auth:deny:{login_id} to trigger old access tokens to refresh. deny = "refresh:{ts}" means old tokens with iat <= ts must refresh; deny = "banned" means the account is banned and both access and refresh are rejected.
Operation Logs
System routes use #[log] heavily:
#[log] injects OperationLogContext and captures method, URL, query, User-Agent, client IP, the user from the login session, and duration. Logs are not written synchronously on the main request path. They are pushed to OperationLogCollector, then batched into sys.operation_log by LogBatchCollectorPlugin.
Sensitive endpoints should explicitly disable parameter or response logging. Login and password reset, for example, use save_params = false.
