[SHIRO-457] Set SecurityManager in createSubject() 83/head
authorMike M Pestorich <mike@swarmbox.com>
Mon, 28 Jan 2019 20:37:29 +0000 (12:37 -0800)
committerMike M Pestorich <mike@swarmbox.com>
Mon, 28 Jan 2019 20:37:29 +0000 (12:37 -0800)
When one does not use a static SecurityManager an exception is thrown
every time a new (unauthenticated) subject successfully logs in. See
the associated JIRA issue:

    https://issues.apache.org/jira/browse/SHIRO-457

This commit ensures Subject.login() will first use the SecurityManager
passed to its Subject.Builder (if one was specified) instead of
immediately starting with the one found in the ThreadContext or
statically in SecurityUtils.

core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
core/src/test/java/org/apache/shiro/mgt/DefaultSecurityManagerTest.java

index a2c8341..235c877 100644 (file)
@@ -181,6 +181,7 @@ public class DefaultSecurityManager extends SessionsSecurityManager {
         context.setAuthenticated(true);
         context.setAuthenticationToken(token);
         context.setAuthenticationInfo(info);
+        context.setSecurityManager(this);
         if (existing != null) {
             context.setSubject(existing);
         }
index cfa3c2b..d8b9650 100644 (file)
@@ -19,6 +19,7 @@
 package org.apache.shiro.mgt;
 
 import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.UnavailableSecurityManagerException;
 import org.apache.shiro.authc.AuthenticationToken;
 import org.apache.shiro.authc.UsernamePasswordToken;
 import org.apache.shiro.config.Ini;
@@ -27,6 +28,8 @@ import org.apache.shiro.session.ExpiredSessionException;
 import org.apache.shiro.session.Session;
 import org.apache.shiro.session.mgt.AbstractValidatingSessionManager;
 import org.apache.shiro.subject.Subject;
+import org.apache.shiro.subject.support.DelegatingSubject;
+import org.apache.shiro.util.ThreadContext;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -153,4 +156,31 @@ public class DefaultSecurityManagerTest extends AbstractSecurityManagerTest {
         assertNull(subject.getPrincipals());
 
     }
+
+    /**
+     * Test ensures that a {@link Subject#login(AuthenticationToken)} first uses
+     * the {@link SecurityManager} passed to its {@link Subject.Builder}
+     * (if one was) instead of the one found in either the {@link ThreadContext}
+     * or statically in {@link SecurityUtils}, either of which may not exist.
+     * <a href="https://issues.apache.org/jira/browse/SHIRO-457">SHIRO-457</a>
+     */
+    @Test
+    public void testNewSubjectWithoutThreadSecurityManager() {
+        // Ensure no fallback sm exists in thread context or statically
+        SecurityUtils.setSecurityManager(null);
+        try {
+            SecurityUtils.getSecurityManager();
+        } catch (UnavailableSecurityManagerException e) {
+            assertTrue(e.getMessage().startsWith("No SecurityManager accessible"));
+        }
+
+        // Specify sm to use and build subject with
+        DelegatingSubject subject =
+            (DelegatingSubject)(new Subject.Builder(sm)).buildSubject();
+
+        // Login and verify specified sm is used and no error thrown
+        AuthenticationToken token = new UsernamePasswordToken("guest", "guest");
+        subject.login(token);
+        assertEquals(sm, subject.getSecurityManager());
+    }
 }