跪拜 Guibai
← All articles
Backend · Java · Open Source

Sa-Token's Same-Token Locks Down Internal Services from Direct Calls

By 小风筝 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Direct access to internal services is a common gap in microservice deployments, especially when network policies alone aren't enough. Same-Token adds a lightweight, framework-integrated enforcement layer that works across REST, Feign, Dubbo, and gRPC without an external auth server.

Summary

Microservices exposed behind a gateway still need a way to reject requests that bypass the gateway entirely. Sa-Token's Same-Token module solves this by injecting a short-lived shared token at the gateway and verifying it in every downstream service. The token lives in Redis, rotates on a schedule, and tolerates brief overlap between old and new tokens so that in-flight requests don't fail during a refresh. The same mechanism extends to internal RPC calls: Feign interceptors and Dubbo filters can attach and verify the token, blocking any caller that lacks it. A single YAML flag enables automatic token injection and verification for Dubbo and gRPC, while a manual filter approach gives teams room to attach custom metadata like tenant IDs.

Takeaways
Same-Token is a shared credential stored in Redis with a default 24-hour lifetime, configurable via sa-token.same-token-timeout.
A gateway filter appends the SA-SAME-TOKEN header; sub-services reject any request missing a valid token.
Token refresh keeps the old token as a secondary credential until the next refresh, preventing failures during rotation.
A scheduled task in a dedicated service refreshes the token on a cron (e.g., every 5 minutes) to avoid race conditions in high-concurrency setups.
Feign integration requires a RequestInterceptor that adds the token header; the called service verifies it with a global servlet filter.
Dubbo and gRPC can enable Same-Token with a single config flag (check-same-token: true), or through manual Consumer/Provider filters for custom attachments.
The sa-token-dubbo plugin also propagates Sa-Token login sessions across RPC boundaries, though SaStorage data and response header manipulation don't transfer.
Redis 6.0+ is required starting from Sa-Token v1.46.0 because the Redis plugin uses SET KEEPTTL.
Conclusions

Same-Token is effectively a lightweight alternative to OAuth2 client credentials for service-to-service auth, trading formal token endpoints for a shared secret rotated on a timer.

The dual-token overlap during refresh is a pragmatic design choice that avoids distributed coordination, but it means a compromised token remains valid until the next refresh cycle completes.

Sa-Token's Dubbo integration solves a real pain point: RPC calls in Dubbo strip out the HTTP context, so without explicit token propagation, any security check on the provider side fails with a null context error.

Concepts & terms
Same-Token
A shared, time-limited credential generated by Sa-Token and stored in Redis. It is used to authenticate that a request originated from a trusted source (gateway or internal service) rather than a direct external call.
Sa-Token
An open-source Java authentication and authorization framework that handles login, permissions, SSO, OAuth2, and microservice gateway authentication with a unified API.
Dubbo Context Loss
In Dubbo RPC, the HTTP request context (headers, session) is not automatically transmitted to the provider. The sa-token-dubbo plugin restores this context and propagates tokens so that auth checks work on both sides of the call.
From the discussion
Featured comments
乌云下的风

why does the application service still need to reference satoken? shouldn't only the login and gateway modules reference satoken

小风筝

same-token itself has nothing to do with login and is not the same thing as a session token. same-token is only responsible for verifying the call source; it won't let through anything that isn't a gateway or internal RPC call.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗