Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 35 additions & 16 deletions src/main/java/org/apache/shiro/site/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.apache.shiro.site;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
Expand All @@ -30,6 +31,9 @@
public final class Validator implements Runnable {
private final Path content;

// JBake headers are in the first few lines, no need to read entire files
private static final int MAX_HEADER_LINES = 50;

private Validator(final Path content) {
this.content = content;
}
Expand Down Expand Up @@ -61,25 +65,40 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr
}

private void doValidateContent(final Path file, final List<String> errors) throws IOException {
final var lines = Files.readAllLines(file); // don't use asciidoctorj to parse properly the adoc, it is way too slow to start
if (missDate(lines) &&
isNotRedirect(lines) &&
isNotTODO(lines)) {
errors.add("Missing date in '" + content.relativize(file) + "'");
}
}
// Only read header lines - JBake metadata is always at the top
// This avoids reading entire files which can be hundreds of lines
try (BufferedReader reader = Files.newBufferedReader(file)) {
String line;
int lineCount = 0;
boolean hasDate = false;
boolean isRedirect = false;
boolean hasTodo = false;

// if the page is not written, no big deal to be broken
private boolean isNotTODO(final List<String> lines) {
return !(lines.size() < 10 && lines.contains("TODO"));
}
while ((line = reader.readLine()) != null && lineCount < MAX_HEADER_LINES) {
lineCount++;

private boolean isNotRedirect(final List<String> lines) {
return lines.stream().noneMatch(":jbake-type: redirect"::equals);
}
if (line.startsWith(":jbake-date:")) {
hasDate = true;
return; // valid, no need to check further
}
if (":jbake-type: redirect".equals(line)) {
isRedirect = true;
return; // redirect pages don't need date validation
}
if ("TODO".equals(line)) {
hasTodo = true;
}
}

// If page is a TODO stub (small file with TODO marker), skip validation
if (lineCount < 10 && hasTodo) {
return;
}

private boolean missDate(final List<String> lines) {
return lines.stream().noneMatch(l -> l.startsWith(":jbake-date:"));
if (!hasDate && !isRedirect) {
errors.add("Missing date in '" + content.relativize(file) + "'");
}
}
}

public static void main(final String... args) throws IOException {
Expand Down
121 changes: 117 additions & 4 deletions src/site/content/authenticator.adoc
Original file line number Diff line number Diff line change
@@ -1,8 +1,121 @@
= Authenticator
:jbake-type: lend_a_hand
[#Authenticator-UnderstandingAuthenticators]
= Apache Shiro Authenticators
:jbake-date: 2010-03-18 00:00:00
:jbake-type: page
:jbake-status: published
:jbake-tags: documentation, todo, lend-a-hand
:jbake-tags: authenticator, authentication, security, realms
:jbake-description: Understanding Apache Shiro Authenticators - the component responsible for verifying user identity. Learn how Authenticators work with Realms and AuthenticationStrategies.
:idprefix:
:icons: font
:toc:

TODO
An `Authenticator` is a component responsible for verifying that a user actually is who they claim to be.
It is the core component that executes the authentication process on behalf of the link:/subject.html[Subject].

While the link:/authentication.html[Authentication] documentation explains the concepts and workflow of authentication in Shiro,
the Authenticator represents the actual implementation component that performs identity verification.

[#Authenticator-Role]
== Role in the SecurityManager

The link:/securitymanager.html[SecurityManager] does not perform authentication directly.
Instead, it delegates authentication requests to its internal `Authenticator` instance.
When a link:/subject.html[Subject] calls link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#login(org.apache.shiro.authc.AuthenticationToken)[`login(token)`],
the SecurityManager receives the request and immediately delegates to the Authenticator by calling
link:/static/current/apidocs/org/apache/shiro/authc/Authenticator.html#authenticate(org.apache.shiro.authc.AuthenticationToken)[`authenticate(token)`].

The Authenticator takes the submitted link:/static/current/apidocs/org/apache/shiro/authc/AuthenticationToken.html[`AuthenticationToken`]
and uses it to verify the Subject's identity.
If verification succeeds, it returns an link:/static/current/apidocs/org/apache/shiro/authc/AuthenticationInfo.html[`AuthenticationInfo`] object.
If verification fails, it throws an link:/static/current/apidocs/org/apache/shiro/authc/AuthenticationException.html[`AuthenticationException`].

[#Authenticator-ModularRealmAuthenticator]
== ModularRealmAuthenticator

Shiro uses the link:/static/current/apidocs/org/apache/shiro/authc/pam/ModularRealmAuthenticator.html[`ModularRealmAuthenticator`]
by default.
This implementation supports coordinating one or more link:/realm.html[Realms] during the authentication process.

When an authentication token is submitted, the ModularRealmAuthenticator:

* Iterates through configured Realms
* Calls each Realm's link:/static/current/apidocs/org/apache/shiro/realm/Realm.html#supports(org.apache.shiro.authc.AuthenticationToken)[`supports(token)`] method to determine if the Realm can process the token
* If a Realm supports the token, its link:/static/current/apidocs/org/apache/shiro/realm/Realm.html#getAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)[`getAuthenticationInfo(token)`] method is invoked
* Returns authentication information if successful, or throws an exception if failed

[#Authenticator-SingleVsMultipleRealms]
== Single vs. Multiple Realms

The ModularRealmAuthenticator supports both configurations:

*Single Realm*:
When only one Realm is configured, the Authenticator directly invokes that Realm to verify the Subject's credentials.

*Multiple Realms*:
When multiple Realms are configured, the Authenticator uses an link:/static/current/apidocs/org/apache/shiro/authc/pam/AuthenticationStrategy.html[`AuthenticationStrategy`]
to determine how to coordinate authentication across the Realms.
This is a link:https://en.wikipedia.org/wiki/Pluggable_Authentication_Modules[PAM]-style approach where each Realm can be consulted in sequence.

[#Authenticator-AuthenticationStrategy]
== AuthenticationStrategy

When multiple Realms are configured, the Authenticator must determine if the overall authentication attempt succeeds or fails.
The link:/static/current/apidocs/org/apache/shiro/authc/pam/AuthenticationStrategy.html[`AuthenticationStrategy`] makes this determination.

Shiro provides three built-in strategies:

* *FirstSuccessfulStrategy*: Consults Realms in order until one succeeds. Remaining Realms are not consulted.
* *AtLeastOneSuccessfulStrategy*: Returns success if at least one Realm succeeds. Other Realms continue to be consulted.
* *AllSuccessfulStrategy*: All Realms must succeed for authentication to succeed. This is the most restrictive.

You can configure which strategy the Authenticator uses, or implement your own strategy for custom behavior.

[#Authenticator-Configuration]
== Configuration

You can configure a custom Authenticator in your Shiro configuration if needed:

[source,ini]
----
authenticator = com.foo.bar.CustomAuthenticator
securityManager.authenticator = $authenticator
----

You can also configure the AuthenticationStrategy:

[source,ini]
----
authenticationStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
authenticator.authenticationStrategy = $authenticationStrategy
----

However, in most cases, the default ModularRealmAuthenticator with the default strategy is sufficient for typical applications.

[#Authenticator-RealmInteraction]
== How Authenticators Work with Realms

The Authenticator does not directly know how to verify credentials.
Instead, it coordinates with configured Realms to perform the actual verification.

A link:/realm.html[Realm] is a security-specific data access object that can locate and validate user credentials from a data source
(database, LDAP, file system, etc.).
The Realm is responsible for:

* Determining if it understands the submitted AuthenticationToken via its `supports(token)` method
* Looking up the user in the data source
* Comparing submitted credentials with those stored in the data source
* Returning the user's authentication information if credentials match
* Throwing an exception if credentials do not match

The Authenticator simply orchestrates this process by delegating to Realms in order and handling the results according to its configured strategy.

[#Authenticator-SeeAlso]
== See Also

To learn more about related topics, see:

* link:authentication.html[Authentication] - Conceptual overview of authentication in Shiro.
* link:java-authentication-guide.html[Java Authentication Guide] - Practical guide to implementing authentication in your application.
* link:realm.html[Realms] - How Realms connect Shiro to your data sources.
* link:authorizer.html[Authorizers] - The counterpart component for authorization.
* link:securitymanager.html[SecurityManager] - The component that orchestrates Authenticators and other Shiro components.
146 changes: 142 additions & 4 deletions src/site/content/authorizer.adoc
Original file line number Diff line number Diff line change
@@ -1,8 +1,146 @@
= Authorizer
:jbake-type: lend_a_hand
[#Authorizer-UnderstandingAuthorizers]
= Apache Shiro Authorizers
:jbake-date: 2010-03-18 00:00:00
:jbake-type: page
:jbake-status: published
:jbake-tags: documentation, todo, lend-a-hand
:jbake-tags: authorizer, authorization, access-control, permissions, roles
:jbake-description: Understanding Apache Shiro Authorizers - the component that determines what authenticated users are allowed to do. Learn how Authorizers work with Realms to evaluate permissions and roles.
:idprefix:
:icons: font
:toc:

TODO
An `Authorizer` is a component responsible for determining whether a user is allowed to perform a certain action.
It evaluates whether a `Subject` has the necessary permissions or roles to access a resource or perform an operation.

While the link:/authorization.html[Authorization] documentation explains the concepts and workflow of access control in Shiro,
the Authorizer represents the actual implementation component that performs access control decisions.

[#Authorizer-Role]
== Role in the SecurityManager

The link:/securitymanager.html[SecurityManager] does not perform authorization checks directly.
Instead, it delegates authorization decisions to its internal `Authorizer` instance.
When a link:/subject.html[Subject] calls authorization methods such as
link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#hasRole(java.lang.String)[`hasRole(role)`],
link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#isPermitted(org.apache.shiro.authz.Permission)[`isPermitted(permission)`],
or their variants, the SecurityManager delegates to the Authorizer.

The Authorizer determines whether the Subject is permitted to perform the requested action by checking the Subject's roles and permissions.
If the Subject has the necessary role or permission, the authorization check passes.
If not, an link:/static/current/apidocs/org/apache/shiro/authz/AuthorizationException.html[`AuthorizationException`] may be thrown.

[#Authorizer-ModularRealmAuthorizer]
== ModularRealmAuthorizer

Shiro uses the link:/static/current/apidocs/org/apache/shiro/authz/ModularRealmAuthorizer.html[`ModularRealmAuthorizer`]
by default.
This implementation supports coordinating one or more link:/realm.html[Realms] during the authorization process.

When an authorization check is performed, the ModularRealmAuthorizer:

* Iterates through configured Realms
* For each Realm that implements the `Authorizer` interface, calls the corresponding authorization method
(`hasRole*`, `checkRole*`, `isPermitted*`, or `checkPermission*`)
* Aggregates and evaluates the results according to Shiro's authorization semantics
* Returns the authorization decision to the caller

It is important to note that the ModularRealmAuthorizer treats Realms differently depending on whether they implement the `Authorizer` interface.
If a Realm does not implement `Authorizer`, it is not consulted for authorization checks.

[#Authorizer-PermissionAndRoleChecks]
== Permission and Role Checks

The Authorizer performs two types of authorization checks:

[#Authorizer-PermissionChecks]
=== Permission Checks

Permission checks verify whether a Subject is allowed to perform a specific action on a specific resource.
Methods for permission checks include:

* link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#isPermitted(org.apache.shiro.authz.Permission)[`isPermitted(permission)`] - returns `true` or `false`
* link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#checkPermission(org.apache.shiro.authz.Permission)[`checkPermission(permission)`] - throws an exception on failure

For example:

[source,java]
----
if (subject.isPermitted("account:read")) {
//User can read accounts
}

subject.checkPermission("document:delete:report123");
----

[#Authorizer-RoleChecks]
=== Role Checks

Role checks verify whether a Subject has a specific role. Methods for role checks include:

* link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#hasRole(java.lang.String)[`hasRole(role)`] - returns `true` or `false`
* link:/static/current/apidocs/org/apache/shiro/subject/Subject.html#checkRole(java.lang.String)[`checkRole(role)`] - throws an exception on failure

For example:

[source,java]
----
if (subject.hasRole("admin")) {
//User is an administrator
}

subject.checkRole("user");
----

[#Authorizer-Configuration]
== Configuration

You can configure a custom Authorizer in your Shiro configuration if needed:

[source,ini]
----
authorizer = com.foo.bar.CustomAuthorizer
securityManager.authorizer = $authorizer
----

However, in most cases, the default ModularRealmAuthorizer is sufficient for typical applications.

[#Authorizer-RealmInteraction]
== How Authorizers Work with Realms

The Authorizer does not directly know where to retrieve authorization data.
Instead, it coordinates with configured Realms to perform the actual authorization checks.

A link:/realm.html[Realm] is a security-specific data access object that knows how to retrieve authorization data from a data source
(database, LDAP, file system, etc.).
The Realm is responsible for:

* Determining if it implements the `Authorizer` interface (which indicates it can perform authorization checks)
* Retrieving the Subject's roles and permissions from the data source
* Evaluating whether the Subject has the requested role or permission
* Returning the results of the authorization check

The Authorizer simply orchestrates this process by delegating to Realms and aggregating their results.
This allows you to use multiple Realms where authorization data may come from different sources,
and Shiro will coordinate the results appropriately.

[#Authorizer-MultipleRealms]
== Authorization with Multiple Realms

When multiple Realms are configured, the ModularRealmAuthorizer consults all Realms that implement the `Authorizer` interface.
The results are aggregated to determine the final authorization decision.

Typically, if any Realm grants permission or role membership, the authorization check succeeds.
However, the exact behavior depends on the authorization data model and how the Realms are configured.
Custom Authorizer implementations can be used to implement different aggregation strategies if needed.

[#Authorizer-SeeAlso]
== See Also

To learn more about related topics, see:

* link:authorization.html[Authorization] - Conceptual overview of authorization in Shiro.
* link:java-authorization-guide.html[Java Authorization Guide] - Practical guide to implementing authorization in your application.
* link:permissions.html[Permissions] - Understanding Shiro's permission model.
* link:realm.html[Realms] - How Realms connect Shiro to your data sources.
* link:authenticator.html[Authenticators] - The counterpart component for authentication.
* link:securitymanager.html[SecurityManager] - The component that orchestrates Authorizers and other Shiro components.
6 changes: 6 additions & 0 deletions src/site/content/blog/2024/11/apache-shiro-202-released.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ You can learn more on link:https://github.com/apache/shiro/releases/tag/shiro-ro

Download and verification instructions are available link:/download.html[on our download page].

== Migration Notes

This is a maintenance release within the 2.x series. If you are already running Shiro 2.x, upgrading to 2.0.2 should be straightforward with no breaking changes expected.

If you are upgrading from Shiro 1.x, please review the link:/migration-guide.html[Migration Guide] for important changes between major versions.

== Documentation

For more information on link:/documentation.html[Shiro, please read the documentation.]
Expand Down
6 changes: 6 additions & 0 deletions src/site/content/blog/2025/07/apache-shiro-205-released.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ You can learn more on link:https://github.com/apache/shiro/releases/tag/shiro-ro

Download and verification instructions are available link:/download.html[on our download page].

== Migration Notes

This is a maintenance release within the 2.x series. If you are already running Shiro 2.x, upgrading to 2.0.5 should be straightforward with no breaking changes expected.

If you are upgrading from Shiro 1.x, please review the link:/migration-guide.html[Migration Guide] for important changes between major versions.

== Documentation

For more information on link:/documentation.html[Shiro, please read the documentation.]
Expand Down
6 changes: 6 additions & 0 deletions src/site/content/blog/2025/11/apache-shiro-206-released.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ You can learn more on link:https://github.com/apache/shiro/releases/tag/shiro-ro

Download and verification instructions are available link:/download.html[on our download page].

== Migration Notes

This is a maintenance release within the 2.x series. If you are already running Shiro 2.x, upgrading to 2.0.6 should be straightforward with no breaking changes expected.

If you are upgrading from Shiro 1.x, please review the link:/migration-guide.html[Migration Guide] for important changes between major versions.

== Documentation

For more information on link:/documentation.html[Shiro, please read the documentation.]
Expand Down
Loading