JWT authentication and authorization extension for Apache Shiro, built on shiro-biz and jwt-issuer-api (easy4j). It provides JWT-aware filters (header X-Authorization or token parameter), stateful/stateless realms, principal repositories, credentials matching and i18n messages for Shiro-based applications.
- 1. Project Overview
- 2. Features & Status
- 3. Requirements & Compatibility
- 4. Architecture & Modules
- 5. Installation
- 6. Quick Start
- 7. Configuration
- 8. Core Usage / API
- 9. Testing & Build
- 10. Versioning & Branches
- 11. Contributing & License
What it is
shiro-jwt-extension brings JWT login to Shiro web applications:
JwtAuthenticatingFilter(extendsTrustableRestAuthenticatingFilterfromshiro-biz) accepts JWTs from theX-Authorizationheader or thetokenrequest parameter.JwtStatefulAuthorizingRealm/JwtStatelessAuthorizingRealmcover session-based and stateless JWT authentication.JwtPayloadRepository/JwtPrincipalRepository/JwtPayloadPrincipalmap JWT payloads (fromjwt-issuer-api) onto the Shiro principal model.JwtAuthorizationFilterandJwtWithinExpiryFilterenforce authorization and expiry checks.ShiroJwtMessageSourceprovides i18n authentication/authorization messages (EN / zh-CN).
What it is not
- It is not a JWT signing/verification library — token issuance and parsing are delegated to
io.github.easy4j:jwt-issuer-api(JwtPayload). - It is not a Spring Boot starter; filters/realms must be wired into your Shiro configuration.
Typical scenarios
| Scenario | Description |
|---|---|
| REST API JWT authentication | JwtAuthenticatingFilter extracts the JWT from X-Authorization / token and authenticates it. |
| Stateless JWT services | JwtStatelessAuthorizingRealm for services without server-side sessions. |
| Session-based JWT | JwtStatefulAuthorizingRealm for classic session applications. |
| Expiry enforcement | JwtWithinExpiryFilter rejects requests whose JWT is no longer within the expiry window. |
| Capability | Status | Notes |
|---|---|---|
| JWT authenticating filter | Available | JwtAuthenticatingFilter — X-Authorization header or token parameter; extends TrustableRestAuthenticatingFilter. |
| Stateful / stateless realms | Available | JwtStatefulAuthorizingRealm, JwtStatelessAuthorizingRealm. |
| Payload & principal repository | Available | JwtPayloadRepository (interface), JwtPrincipalRepository, JwtPayloadPrincipal. |
| Credentials matching | Available | JwtCredentialsMatcher. |
| Authorization filters | Available | JwtAuthorizationFilter, JwtWithinExpiryFilter (X-Authorization / token). |
| Handlers | Available | JwtAuthenticationFailureHandler, JwtAuthenticationSuccessHandler (payload repository + expiry check), JwtAuthorizationFailureHandler (all Ordered). |
| Subject factory | Available | JwtSubjectFactory (session-creation enabled/disabled). |
| Tokens | Available | JwtAuthenticationToken (extends DefaultAuthenticationToken), JwtAuthorizationToken. |
| Exceptions | Available | ExpiredJwtException, IncorrectJwtException, InvalidJwtToken, NotObtainedJwtException. |
| i18n messages | Available | messages.properties (+ en_US, zh_CN) via ShiroJwtMessageSource. |
| Utilities | Available | SubjectJwtUtils, JSONResult, StringUtils (under org.apache.shiro.spring.boot.utils). |
Status is reported as of
2.0.x.x.20260630-SNAPSHOTon thefeature/2.0.xbranch.
| Item | Version |
|---|---|
| JDK | 17+ |
| Maven | 3.0+ (Maven Wrapper 3.5.0 bundled) |
| Apache Shiro | 1.13.0 (shiro-core, shiro-web) |
| easy4j dependencies | shiro-biz, jwt-issuer-api (both 2.0.x.x.20260630-SNAPSHOT) |
| JSON | fastjson 2.0.62, jackson-databind 2.17.2 |
| Other | spring-context / spring-web, commons-lang3, guava, javax.servlet-api 4.0.1 |
Version lines
| Branch | JDK baseline | Version pattern |
|---|---|---|
feature/1.0.x |
JDK 8 | 1.0.x.* |
feature/2.0.x |
JDK 17 | 2.0.x.* |
feature/3.0.x |
JDK 21 | 3.0.x.* |
Client (JWT in X-Authorization header / token parameter)
|
v
JwtAuthenticatingFilter (authc)
| createJwtToken() -> JwtAuthenticationToken
v
JwtStatefulAuthorizingRealm / JwtStatelessAuthorizingRealm
| JwtPrincipalRepository -> JwtPayloadRepository (jwt-issuer-api)
| JwtCredentialsMatcher
v
Subject (JwtPayloadPrincipal)
|
v
JwtAuthorizationFilter / JwtWithinExpiryFilter (authz)
|
+-- handlers --> ShiroJwtMessageSource (i18n)
This is a single-module project (packaging jar), classes under org.apache.shiro.spring.boot.jwt (plus org.apache.shiro.spring.boot.utils):
| Package | Role |
|---|---|
jwt |
Principal/payload repositories, message source |
jwt.authc (+ jwt.authc.credential) |
JWT authenticating filter, handlers, subject factory, credentials matcher |
jwt.authz |
Authorization filter, within-expiry filter, failure handler |
jwt.realm |
Stateful and stateless JWT realms |
jwt.token |
JwtAuthenticationToken, JwtAuthorizationToken |
jwt.exception |
JWT-specific authentication exceptions |
utils |
SubjectJwtUtils, JSONResult, StringUtils |
The artifact is not yet published to Maven Central. Resolve it from the project's configured artifact repository (Aliyun Packages) or install it locally from source; the snapshot version currently used on the feature/2.0.x branch is 2.0.x.x.20260630-SNAPSHOT.
Maven
<dependency>
<groupId>io.github.easy4j</groupId>
<artifactId>shiro-jwt-extension</artifactId>
<version>2.0.x.x.20260630-SNAPSHOT</version>
</dependency>Gradle
implementation 'io.github.easy4j:shiro-jwt-extension:2.0.x.x.20260630-SNAPSHOT'Wire the JWT authenticating filter into your Shiro filter chain:
import org.apache.shiro.spring.boot.jwt.authc.JwtAuthenticatingFilter;
import org.apache.shiro.spring.boot.jwt.realm.JwtStatelessAuthorizingRealm;
// 1. Stateless realm (no server-side session required)
JwtStatelessAuthorizingRealm realm = new JwtStatelessAuthorizingRealm();
// 2. Filter: accepts "X-Authorization: <jwt>" or "?token=<jwt>"
JwtAuthenticatingFilter filter = new JwtAuthenticatingFilter();
filter.setLoginUrl("/login/jwt");
// register filter + realm with your SecurityManager / filter chainExpected result: requests carrying a valid JWT are authenticated by the realm; the Shiro subject principal becomes the JwtPayloadPrincipal extracted from the token payload; requests without a valid JWT are redirected to the login URL.
This library has no configuration properties or prefix; it is configured programmatically:
| Extension point | Configurable via |
|---|---|
JwtAuthenticatingFilter |
setLoginUrl(...), request parameter name (default token) and header name (default X-Authorization). |
JwtAuthenticationSuccessHandler |
constructor (JwtPayloadRepository, boolean checkExpiry) |
JwtPrincipalRepository |
constructor (JwtPayloadRepository), setCheckExpiry(boolean) |
JwtSubjectFactory |
constructor (boolean sessionCreationEnabled) |
| Message texts | bundled org/apache/shiro/spring/boot/jwt/messages*.properties |
| Class | Role |
|---|---|
JwtAuthenticatingFilter |
Extracts JWT from X-Authorization header / token parameter and authenticates (AUTHORIZATION_HEADER, AUTHORIZATION_PARAM constants). |
JwtAuthorizationFilter |
Authorization filter using the same header/parameter extraction. |
JwtWithinExpiryFilter |
Rejects JWTs outside the expiry window. |
JwtStatefulAuthorizingRealm / JwtStatelessAuthorizingRealm |
Realms for session-based / stateless JWT auth. |
JwtPayloadRepository / JwtPrincipalRepository / JwtPayloadPrincipal |
JWT payload → Shiro principal mapping. |
JwtCredentialsMatcher |
Credentials matching for JWT tokens. |
ShiroJwtMessageSource |
ResourceBundleMessageSource subclass; getAccessor() returns the MessageSourceAccessor. |
# Full build with JaCoCo coverage report/check
./mvnw clean verify
# Install into the local repository
./mvnw installTest & gate facts (as configured in the pom):
- No unit tests exist in this module yet.
- JaCoCo is bound to
prepare-agent/report/check; thecheckrule requires a 90% line coverage ratio (configured withhaltOnFailure=false).
| Branch | JDK baseline | Version pattern | Status |
|---|---|---|---|
feature/1.0.x |
JDK 8 | 1.0.x.* |
Active; current snapshot 1.0.x.20260630-SNAPSHOT |
feature/2.0.x |
JDK 17 | 2.0.x.* |
Maintained |
feature/3.0.x |
JDK 21 | 3.0.x.* |
Maintained |
Maintenance strategy: the 1.0.x line keeps JDK 8 compatibility for legacy deployments; the 2.0.x and 3.0.x lines are the modern JDK baselines. Release artifacts are published to the project's configured artifact repository (Aliyun Packages) and GitHub Releases; the project has not yet published to Maven Central.
Contributions are welcome — please open an issue or a pull request on the GitHub repository.
This project is licensed under the Apache License 2.0. See LICENSE for details.