diff --git a/src/main/java/org/apache/shiro/site/Validator.java b/src/main/java/org/apache/shiro/site/Validator.java index 72f5c23d46..55923d6dbf 100644 --- a/src/main/java/org/apache/shiro/site/Validator.java +++ b/src/main/java/org/apache/shiro/site/Validator.java @@ -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; @@ -30,6 +31,11 @@ public final class Validator implements Runnable { private final Path content; + // JBake headers are always in the first few lines of .adoc files. + // Verified empirically: all files in this repo have jbake-date within lines 2-22. + // 50 provides a safe margin while avoiding reading entire files. + private static final int MAX_HEADER_LINES = 50; + private Validator(final Path content) { this.content = content; } @@ -61,25 +67,40 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr } private void doValidateContent(final Path file, final List 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 lines) { - return !(lines.size() < 10 && lines.contains("TODO")); - } + while ((line = reader.readLine()) != null && lineCount < MAX_HEADER_LINES) { + lineCount++; - private boolean isNotRedirect(final List 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 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 { diff --git a/src/site/content/authenticator.adoc b/src/site/content/authenticator.adoc index 5cb29fd438..327c40abe1 100644 --- a/src/site/content/authenticator.adoc +++ b/src/site/content/authenticator.adoc @@ -1,8 +1,110 @@ -= 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. diff --git a/src/site/content/authorizer.adoc b/src/site/content/authorizer.adoc index 7b9ca4a8f5..076aabd89d 100644 --- a/src/site/content/authorizer.adoc +++ b/src/site/content/authorizer.adoc @@ -1,8 +1,134 @@ -= 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. diff --git a/src/site/content/community.adoc b/src/site/content/community.adoc index e71a446f9f..98488fdfa5 100644 --- a/src/site/content/community.adoc +++ b/src/site/content/community.adoc @@ -30,8 +30,6 @@ At the Shiro project we make it easy for anyone to join our great community and * *link:developer-resources.html[Developer Resources]* - Helpful information for anyone providing project help as a committer or contributor -* *https://github.com/apache/shiro/discussions[GitHub Discussions]* - For questions, ideas, and community discussion - -* *https://github.com/apache/shiro/issues[GitHub Issues]* - For bug reports and feature requests +* *https://github.com/apache/shiro/issues[Issue Tracker]* - Once you're ready to contribute, this is a good place to see what needs to get done * *https://www.apache.org/foundation/sponsorship.html[Donate to ASF]* - Shiro is a project under the Apache Software Foundation, a non-profit that relies on donations and community support diff --git a/src/site/content/forums.adoc b/src/site/content/forums.adoc index 2dc919c6b2..02f56f571d 100644 --- a/src/site/content/forums.adoc +++ b/src/site/content/forums.adoc @@ -6,18 +6,7 @@ :jbake-description: Access Apache Shiro community forums and mailing list archives via ASF Pony Mail for user and developer discussions. :idprefix: -== Mailing Lists - -For those that may prefer mailing lists, please see the link:mailing-lists.html[Mailing Lists] information. -____ - -*NOTE:* The primary forums for Apache Shiro are the mailing lists, which can be accessed via the link:mailing-lists.html[Mailing Lists] page. This is per the Apache Software Foundation's community guidelines. - -____ - -== Mailing List Archives - -For users that prefer to browse the mailing lists with a browser can use https://lists.apache.org/[ASF Lists] (Pony Mail). +Users who prefer to browse the mailing lists with a browser can use https://lists.apache.org/[ASF Lists] (Pony Mail). * link:++https://lists.apache.org/list.html?user@shiro.apache.org++[Shiro User Forum] @@ -29,7 +18,6 @@ ____ ____ -== GitHub Discussions - -For questions, ideas, and general community discussion, please use https://github.com/apache/shiro/discussions[GitHub Discussions]. +== Mailing Lists +For those that may prefer mailing lists, please see the link:mailing-lists.html[Mailing Lists] information. \ No newline at end of file diff --git a/src/site/content/issues.adoc b/src/site/content/issues.adoc index 79904b4a9a..994160f5f2 100644 --- a/src/site/content/issues.adoc +++ b/src/site/content/issues.adoc @@ -2,8 +2,8 @@ :jbake-date: 2010-03-18 00:00:00 :jbake-type: page :jbake-status: published -:jbake-tags: issues, bugs, jira, bug-tracking, support -:jbake-description: Report bugs, request features, and track issues for Apache Shiro using GitHub Issues tracking system. +:jbake-tags: issues, bugs, bug-tracking, support +:jbake-description: Report bugs, request features, and track issues for Apache Shiro using GitHub Issues. :idprefix: :icons: font