Merge pull request #220 from bmhm/SHIRO-551

[SHIRO-551] Implement toString() for DelegatingSubject.java.
diff --git a/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java b/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java
index 5581b7a..d3040d1 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java
@@ -41,6 +41,7 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.StringJoiner;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -515,4 +516,16 @@
 
         return popped;
     }
+
+    @Override
+    public String toString() {
+        return new StringJoiner(", ", "DelegatingSubject{", "}")
+            .add("principals=" + principals)
+            .add("authenticated=" + authenticated)
+            .add("host='******")
+            .add("session='******'")
+            .add("sessionCreationEnabled=" + sessionCreationEnabled)
+            .add("securityManager=" + securityManager)
+            .toString();
+    }
 }
diff --git a/core/src/test/java/org/apache/shiro/subject/DelegatingSubjectTest.java b/core/src/test/java/org/apache/shiro/subject/DelegatingSubjectTest.java
index ee04e6d..2bc0bbe 100644
--- a/core/src/test/java/org/apache/shiro/subject/DelegatingSubjectTest.java
+++ b/core/src/test/java/org/apache/shiro/subject/DelegatingSubjectTest.java
@@ -216,4 +216,25 @@
 
         LifecycleUtils.destroy(sm);
     }
+
+    @Test
+    public void testToString() {
+        // given
+        String username = "jsmith";
+
+        DefaultSecurityManager securityManager = new DefaultSecurityManager();
+        PrincipalCollection identity = new SimplePrincipalCollection(username, "testRealm");
+        final String hostname = "localhost";
+        final DelegatingSubject sourceSubject = new DelegatingSubject(identity, true, hostname, null, securityManager);
+
+        // when
+        final String subjectToString = sourceSubject.toString();
+
+        // then
+        final Session session = sourceSubject.getSession(true);
+        String sesionId = (String) session.getId();
+        assertFalse("toString must not leak sessionId", subjectToString.contains(sesionId));
+        assertFalse("toString must not leak host", subjectToString.contains(hostname));
+    }
+
 }