diff --git a/src/site/content/support.adoc b/src/site/content/support.adoc index ba6518570..811a5c3c2 100644 --- a/src/site/content/support.adoc +++ b/src/site/content/support.adoc @@ -10,6 +10,7 @@ The Shiro project offers support through its community of users, contributors, a We encourage everyone to participate and use the available community support tools below. +* link:troubleshooting.html[Troubleshooting & FAQ] * link:mailing-lists.html[Mailing Lists] * link:forums.html[Forums] * link:issues.html[Issues and Bug Tracking] diff --git a/src/site/content/troubleshooting.adoc b/src/site/content/troubleshooting.adoc new file mode 100644 index 000000000..cd78bd9cd --- /dev/null +++ b/src/site/content/troubleshooting.adoc @@ -0,0 +1,514 @@ += Troubleshooting & FAQ +:jbake-date: 2026-01-18 00:00:00 +:jbake-type: page +:jbake-status: published +:jbake-tags: documentation, troubleshooting, faq +:idprefix: +:icons: font +:toc: + +This page covers common issues that users encounter when configuring and using Apache Shiro. Each section provides practical solutions and debugging tips to help you resolve problems quickly. + +== Session Management Issues + +=== Why do my sessions expire too quickly? + +By default, Shiro sessions have a 30-minute timeout. If your sessions expire faster than expected, check your `SessionManager` configuration. + +You can adjust the global session timeout in your `shiro.ini`: + +[source,ini] +---- +[main] +# Set session timeout to 1 hour (in milliseconds) +securityManager.sessionManager.globalSessionTimeout = 3600000 +---- + +For Spring Boot applications, you can configure this in `application.properties`: + +[source,properties] +---- +shiro.sessionManager.globalSessionTimeout = 3600000 +---- + +Also verify that your application is calling `session.touch()` when needed for long-running operations, particularly in Rich Internet Application (RIA) scenarios where users may be active on the page without triggering server requests. + +See the link:session-management.html[Session Management] documentation for more details. + +=== How do I configure session clustering? + +Shiro supports session clustering through its `SessionDAO` abstraction. To enable clustering, you need to: + +1. Configure a distributed cache (such as Ehcache, Redis, or Hazelcast) +2. Implement or configure an appropriate `SessionDAO` +3. Set up the `CacheManager` + +Example configuration using Ehcache: + +[source,ini] +---- +[main] +cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager +cacheManager.cacheManagerConfigFile = classpath:ehcache.xml + +sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO +sessionDAO.activeSessionsCacheName = shiro-activeSessionCache + +sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager +sessionManager.sessionDAO = $sessionDAO +sessionManager.cacheManager = $cacheManager + +securityManager.sessionManager = $sessionManager +securityManager.cacheManager = $cacheManager +---- + +Make sure your `ehcache.xml` includes a properly configured distributed cache for the `shiro-activeSessionCache`. + +=== Why are my sessions not persisting across server restarts? + +By default, Shiro uses an in-memory `SessionDAO` that does not persist sessions. To maintain sessions across restarts, you need to configure a persistent `SessionDAO` backed by a database, file system, or distributed cache. + +Consider using `EnterpriseCacheSessionDAO` with a persistent cache or implementing a custom `SessionDAO` that stores sessions in your preferred data store. + +== Authentication Issues + +=== Why is authentication failing even though the credentials are correct? + +There are several common causes for this issue: + +1. **Password encoding mismatch**: Ensure the password stored in your data source uses the same hashing algorithm configured in your Realm. + +2. **Realm not finding the account**: Verify your Realm can locate the user account. Enable debug logging to see what Shiro is doing: ++ +[source,properties] +---- +log4j.logger.org.apache.shiro = DEBUG +---- + +3. **Multiple Realms configured incorrectly**: If you have multiple Realms, check your `AuthenticationStrategy`. The default `AtLeastOneSuccessfulStrategy` requires at least one Realm to succeed. + +4. **Case sensitivity**: Usernames may be case-sensitive depending on your Realm implementation. Verify the case matches exactly. + +=== How do I debug authentication failures? + +Enable Shiro's debug logging to trace the authentication flow: + +[source,xml] +---- + + + +---- + +You can also catch and inspect the `AuthenticationException` for more details: + +[source,java] +---- +try { + currentUser.login(token); +} catch (UnknownAccountException uae) { + log.info("No account found for user: " + token.getPrincipal()); +} catch (IncorrectCredentialsException ice) { + log.info("Incorrect password for user: " + token.getPrincipal()); +} catch (LockedAccountException lae) { + log.info("Account is locked: " + token.getPrincipal()); +} catch (AuthenticationException ae) { + log.error("Unexpected authentication error", ae); +} +---- + +See the link:authentication.html[Authentication] documentation for a complete overview. + +=== What does "There is no configured realm" error mean? + +This error indicates that Shiro cannot find any Realm to authenticate against. You must configure at least one Realm in your application. + +In `shiro.ini`: + +[source,ini] +---- +[main] +myRealm = com.mycompany.security.MyCustomRealm +securityManager.realms = $myRealm +---- + +For Spring Boot, define a Realm bean: + +[source,java] +---- +@Bean +public Realm realm() { + return new MyCustomRealm(); +} +---- + +== Authorization Issues + +=== Why are my permission checks not working as expected? + +Common reasons for permission check failures: + +1. **Incorrect permission string format**: Shiro uses a colon-delimited format. Ensure you're using consistent formatting: ++ +[source,java] +---- +// These are different permissions +subject.isPermitted("document:read"); // domain:action +subject.isPermitted("document:read:123"); // domain:action:instance +---- + +2. **Wildcard permissions**: Understand how wildcards work. `document:*` grants all actions on documents, while `*:read` is typically not valid (wildcards work left-to-right). + +3. **Role vs Permission confusion**: Roles and permissions are different. Use `hasRole()` for role checks and `isPermitted()` for permission checks. + +See the link:permissions.html[Permissions] documentation for the complete wildcard permission syntax. + +=== How do I configure role-based authorization? + +Roles can be assigned to users in your Realm implementation. In your Realm's `doGetAuthorizationInfo` method: + +[source,java] +---- +@Override +protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + String username = (String) principals.getPrimaryPrincipal(); + + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + + // Add roles + info.addRole("user"); + if (isAdmin(username)) { + info.addRole("admin"); + } + + // Add permissions + info.addStringPermission("document:read"); + + return info; +} +---- + +For web applications, you can also use filter chain definitions: + +[source,ini] +---- +[urls] +/admin/** = authc, roles[admin] +/user/** = authc, roles[user] +---- + +== Spring Boot Integration + +=== Why is Shiro not auto-configuring in my Spring Boot application? + +Ensure you have the correct starter dependency: + +For web applications: + +++++ +<@dependencies.dependencies anchorId="web-starter" deps=[{"g":"org.apache.shiro", "a":"shiro-spring-boot-web-starter", "v":"${versions.latestRelease}"}] /> +++++ + +For non-web applications: + +++++ +<@dependencies.dependencies anchorId="cli-starter" deps=[{"g":"org.apache.shiro", "a":"shiro-spring-boot-starter", "v":"${versions.latestRelease}"}] /> +++++ + +Also verify that you have defined a `Realm` bean in your configuration. + +See the link:spring-boot.html[Spring Boot Integration] guide for complete setup instructions. + +=== How do I configure Shiro filter chains in Spring Boot? + +Define a `ShiroFilterChainDefinition` bean in your configuration: + +[source,java] +---- +@Bean +public ShiroFilterChainDefinition shiroFilterChainDefinition() { + DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); + + // Static resources + chainDefinition.addPathDefinition("/css/**", "anon"); + chainDefinition.addPathDefinition("/js/**", "anon"); + + // Login page + chainDefinition.addPathDefinition("/login", "anon"); + + // Admin section requires admin role + chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]"); + + // Everything else requires authentication + chainDefinition.addPathDefinition("/**", "authc"); + + return chainDefinition; +} +---- + +Remember that filter chain order matters. More specific paths should be defined before general ones. + +== Remember Me Issues + +=== Why is "Remember Me" not working? + +Several factors can cause Remember Me to fail: + +1. **Cookie configuration**: The Remember Me cookie may not be set correctly. Check your cookie settings: ++ +[source,ini] +---- +[main] +securityManager.rememberMeManager.cookie.name = rememberMe +securityManager.rememberMeManager.cookie.maxAge = 2592000 +securityManager.rememberMeManager.cookie.path = / +---- + +2. **Cipher key not set**: In production, you should set a consistent cipher key across cluster nodes: ++ +[source,java] +---- +@Bean +public CookieRememberMeManager rememberMeManager() { + CookieRememberMeManager manager = new CookieRememberMeManager(); + manager.setCipherKey(Base64.decode("your-base64-encoded-key")); + return manager; +} +---- + +3. **Using `isAuthenticated()` instead of `isRemembered()`**: These are different states. A remembered user is NOT fully authenticated: ++ +[source,java] +---- +// User who logged in this session +subject.isAuthenticated(); + +// User recognized via Remember Me cookie +subject.isRemembered(); +---- + +=== How do I generate a cipher key for Remember Me? + +Generate a secure key using Shiro's `AesCipherService`: + +[source,java] +---- +AesCipherService cipherService = new AesCipherService(); +Key key = cipherService.generateNewKey(); +String base64Key = Base64.encodeToString(key.getEncoded()); +System.out.println("Cipher key: " + base64Key); +---- + +Store this key securely and use the same key across all nodes in a clustered environment. + +== Realm Configuration + +=== How do I configure multiple Realms? + +Define each Realm and assign them to the `SecurityManager`: + +[source,ini] +---- +[main] +ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealm +ldapRealm.contextFactory.url = ldap://localhost:389 + +jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm +jdbcRealm.dataSource = $dataSource + +securityManager.realms = $ldapRealm, $jdbcRealm +---- + +By default, Shiro uses `AtLeastOneSuccessfulStrategy` for authentication, meaning the user is authenticated if any Realm succeeds. + +See the link:realm.html[Realm] documentation for more advanced configurations. + +=== Why is my custom Realm not being used? + +Verify the following: + +1. The Realm is properly registered with the `SecurityManager` +2. The Realm supports the `AuthenticationToken` type being submitted +3. The Realm is enabled (check `isAuthenticationCachingEnabled` if using caching) + +Override `supports()` in your Realm if you need to handle specific token types: + +[source,java] +---- +@Override +public boolean supports(AuthenticationToken token) { + return token instanceof UsernamePasswordToken; +} +---- + +== Cache Configuration + +=== How do I enable caching for authentication and authorization? + +Configure a `CacheManager` and enable caching in your Realms: + +[source,ini] +---- +[main] +cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager +cacheManager.cacheManagerConfigFile = classpath:ehcache.xml + +securityManager.cacheManager = $cacheManager + +myRealm = com.mycompany.security.MyRealm +myRealm.authenticationCachingEnabled = true +myRealm.authorizationCachingEnabled = true +---- + +Caching can significantly improve performance, especially for authorization lookups that may involve database queries. + +=== Why are my authorization changes not taking effect immediately? + +If you have caching enabled, authorization information is cached for performance. When a user's permissions change, you need to clear their cached authorization: + +[source,java] +---- +// Clear authorization cache for a specific user +PrincipalCollection principals = subject.getPrincipals(); +realm.getAuthorizationCache().remove(principals); +---- + +Or clear the entire cache: + +[source,java] +---- +realm.getAuthorizationCache().clear(); +---- + +== Debug Logging + +=== How do I enable detailed Shiro logging? + +For Log4j2, add these entries to your logging configuration: + +[source,xml] +---- + + + + + + +---- + +For Logback (common in Spring Boot): + +[source,xml] +---- + +---- + +Or in `application.properties`: + +[source,properties] +---- +logging.level.org.apache.shiro=DEBUG +---- + +== Filter Chain Issues + +=== Why are my URL patterns not matching correctly? + +Shiro uses Ant-style path matching. Remember these rules: + +* `*` matches any characters within a path segment +* `**` matches any path segments +* Patterns are evaluated in order; first match wins + +Example patterns: + +[source,ini] +---- +[urls] +/login = anon +/logout = logout +/admin/** = authc, roles[admin] +/api/** = authc, rest +/** = authc +---- + +Place more specific patterns before general ones. The `/**` catch-all should always be last. + +=== What is the difference between authc and anon filters? + +* **anon**: Allows anonymous access; no authentication required +* **authc**: Requires the user to be authenticated (logged in during this session) +* **user**: Allows access if the user is authenticated OR remembered + +Common filter chain: + +[source,ini] +---- +[urls] +/public/** = anon +/login = anon +/account/** = user +/admin/** = authc, roles[admin] +/** = authc +---- + +== Startup and Initialization + +=== Why do I get "SecurityManager is not available" error? + +This error occurs when Shiro's `SecurityUtils.getSubject()` is called before the `SecurityManager` is initialized. + +Ensure the `SecurityManager` is set up before any security operations: + +[source,java] +---- +Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini"); +SecurityManager securityManager = factory.getInstance(); +SecurityUtils.setSecurityManager(securityManager); +---- + +In web applications, verify that Shiro's filter is configured in your `web.xml` or equivalent configuration and loads before your application code runs. + +=== How do I troubleshoot Shiro initialization in a web application? + +Check the following: + +1. **Filter configuration**: Ensure `ShiroFilter` is mapped correctly in your `web.xml`: ++ +[source,xml] +---- + + ShiroFilter + org.apache.shiro.web.servlet.ShiroFilter + + + ShiroFilter + /* + +---- + +2. **Environment listener**: Add the environment loader listener: ++ +[source,xml] +---- + + org.apache.shiro.web.env.EnvironmentLoaderListener + +---- + +3. **Configuration file location**: By default, Shiro looks for `/WEB-INF/shiro.ini`. You can customize this with a context parameter. + +== Additional Resources + +For more detailed information, refer to these documentation pages: + +* link:reference.html[Reference Manual] - Complete Shiro reference documentation +* link:10-minute-tutorial.html[10 Minute Tutorial] - Quick start guide +* link:java-authentication-guide.html[Authentication Guide] - Detailed authentication walkthrough +* link:java-authorization-guide.html[Authorization Guide] - Detailed authorization walkthrough +* link:configuration.html[Configuration] - Configuration options and formats + +If you cannot find a solution here, consider reaching out to the community: + +* link:mailing-lists.html[Mailing Lists] - Ask questions and get help from the community +* link:issues.html[Issue Tracker] - Report bugs or request features diff --git a/src/site/templates/menu.ftl b/src/site/templates/menu.ftl index 6309e61fb..ff241455b 100644 --- a/src/site/templates/menu.ftl +++ b/src/site/templates/menu.ftl @@ -54,6 +54,7 @@
  • Articles
  • News
  • Events
  • +
  • Troubleshooting & FAQ
  • More