shiro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lhazlew...@apache.org
Subject svn commit: r817392 - in /incubator/shiro/trunk: core/src/main/java/org/apache/shiro/authc/ core/src/main/java/org/apache/shiro/mgt/ core/src/main/java/org/apache/shiro/realm/ core/src/main/java/org/apache/shiro/subject/ core/src/test/java/org/apache/s...
Date Mon, 21 Sep 2009 20:06:23 GMT
Author: lhazlewood
Date: Mon Sep 21 20:06:22 2009
New Revision: 817392

URL: http://svn.apache.org/viewvc?rev=817392&view=rev
Log:
SHIRO-105 - added getPrimaryPrincipal() method and default implementation retaining existing
default heuristic (iterator().next() == assumed primary).  Updated various JavaDoc reflecting
this change.

Modified:
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/Subject.java
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/AuthorizingRealmTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
Mon Sep 21 20:06:22 2009
@@ -19,10 +19,10 @@
 
 package org.apache.shiro.authc;
 
-import java.io.Serializable;
-
 import org.apache.shiro.subject.PrincipalCollection;
 
+import java.io.Serializable;
+
 /**
  * <code>AuthenticationInfo</code> represents a Subject's (aka user's) stored
account information relevant to the
  * authentication/log-in process only.
@@ -44,7 +44,7 @@
  * <code>AuthorizationInfo</code>.  Whether you choose to implement these two
interfaces separately or implement the one
  * <code>Account</code> interface for a given <code>Realm</code>
is entirely based on your application's needs or your
  * preferences.
- *
+ * <p/>
  * <p><b>Pleae note:</b>  Since Shiro sometimes logs authentication operations,
please ensure your AuthenticationInfo's
  * <code>toString()</code> implementation does <em>not</em> print
out account credentials (password, etc), as these might be viewable to
  * someone reading your logs.  This is good practice anyway, and account credentials should
rarely (if ever) be printed
@@ -64,10 +64,6 @@
      * information useful to the application such as a username, or user id, a given name,
etc - anything useful
      * to the application to identify the current <code>Subject</code>.
      * <p/>
-     * At least one of these attributes should be the account's 'primary' identifier, such
as a username or unique
-     * user id.  By convention, usually  the first principal (that is, <code>getPrincipals().iterator().next()</code>)
is the
-     * 'primary' one.
-     * <p/>
      * The returned PrincipalCollection should <em>not</em> contain any credentials
used to verify principals, such
      * as passwords, private keys, etc.  Those should be instead returned by {@link #getCredentials()
getCredentials()}.
      *

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java Mon
Sep 21 20:06:22 2009
@@ -18,15 +18,15 @@
  */
 package org.apache.shiro.authc;
 
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Set;
-
 import org.apache.shiro.authz.Permission;
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
 import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.SimplePrincipalCollection;
 
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Set;
+
 
 /**
  * Simple implementation of the {@link org.apache.shiro.authc.Account} interface that
@@ -76,9 +76,9 @@
     /**
      * Constructs a SimpleAccount instance for the specified realm with the given principals
and credentials.
      *
-     * @param principal the 'primary' identifying attribute of the account, for example,
a user id or username.
+     * @param principal   the 'primary' identifying attribute of the account, for example,
a user id or username.
      * @param credentials the credentials that verify identity for the account
-     * @param realmName the name of the realm that accesses this account data
+     * @param realmName   the name of the realm that accesses this account data
      */
     public SimpleAccount(Object principal, Object credentials, String realmName) {
         this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal :
new SimplePrincipalCollection(principal, realmName), credentials);
@@ -86,10 +86,11 @@
 
     /**
      * Constructs a SimpleAccount instance for the specified realm with the given principals
and credentials.
-     * @param principals the identifying attributes of the account, at least one of which
should be considered the
-     * account's 'primary' identifying attribute, for example, a user id or username.
+     *
+     * @param principals  the identifying attributes of the account, at least one of which
should be considered the
+     *                    account's 'primary' identifying attribute, for example, a user
id or username.
      * @param credentials the credentials that verify identity for the account
-     * @param realmName the name of the realm that accesses this account data
+     * @param realmName   the name of the realm that accesses this account data
      */
     public SimpleAccount(Collection principals, Object credentials, String realmName) {
         this(new SimplePrincipalCollection(principals, realmName), credentials);
@@ -97,8 +98,9 @@
 
     /**
      * Constructs a SimpleAccount instance for the specified principals and credentials.
-     * @param principals the identifying attributes of the account, at least one of which
should be considered the
-     * account's 'primary' identifying attribute, for example, a user id or username.
+     *
+     * @param principals  the identifying attributes of the account, at least one of which
should be considered the
+     *                    account's 'primary' identifying attribute, for example, a user
id or username.
      * @param credentials the credentials that verify identity for the account
      */
     public SimpleAccount(PrincipalCollection principals, Object credentials) {
@@ -109,10 +111,10 @@
     /**
      * Constructs a SimpleAccount instance for the specified principals and credentials,
with the assigned roles.
      *
-     * @param principals the identifying attributes of the account, at least one of which
should be considered the
-     * account's 'primary' identifying attribute, for example, a user id or username.
+     * @param principals  the identifying attributes of the account, at least one of which
should be considered the
+     *                    account's 'primary' identifying attribute, for example, a user
id or username.
      * @param credentials the credentials that verify identity for the account
-     * @param roles the names of the roles assigned to this account.
+     * @param roles       the names of the roles assigned to this account.
      */
     public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String>
roles) {
         this.authcInfo = new SimpleAuthenticationInfo(principals, credentials);
@@ -123,10 +125,10 @@
      * Constructs a SimpleAccount instance for the specified realm with the given principal
and credentials, with the
      * the assigned roles and permissions.
      *
-     * @param principal the 'primary' identifying attributes of the account, for example,
a user id or username.
+     * @param principal   the 'primary' identifying attributes of the account, for example,
a user id or username.
      * @param credentials the credentials that verify identity for the account
-     * @param realmName the name of the realm that accesses this account data
-     * @param roleNames the names of the roles assigned to this account.
+     * @param realmName   the name of the realm that accesses this account data
+     * @param roleNames   the names of the roles assigned to this account.
      * @param permissions the permissions assigned to this account directly (not those assigned
to any of the realms).
      */
     public SimpleAccount(Object principal, Object credentials, String realmName, Set<String>
roleNames, Set<Permission> permissions) {
@@ -139,11 +141,11 @@
      * Constructs a SimpleAccount instance for the specified realm with the given principals
and credentials, with the
      * the assigned roles and permissions.
      *
-     * @param principals the identifying attributes of the account, at least one of which
should be considered the
-     * account's 'primary' identifying attribute, for example, a user id or username.
+     * @param principals  the identifying attributes of the account, at least one of which
should be considered the
+     *                    account's 'primary' identifying attribute, for example, a user
id or username.
      * @param credentials the credentials that verify identity for the account
-     * @param realmName the name of the realm that accesses this account data
-     * @param roleNames the names of the roles assigned to this account.
+     * @param realmName   the name of the realm that accesses this account data
+     * @param roleNames   the names of the roles assigned to this account.
      * @param permissions the permissions assigned to this account directly (not those assigned
to any of the realms).
      */
     public SimpleAccount(Collection principals, Object credentials, String realmName, Set<String>
roleNames, Set<Permission> permissions) {
@@ -156,10 +158,10 @@
      * Constructs a SimpleAccount instance from the given principals and credentials, with
the
      * the assigned roles and permissions.
      *
-     * @param principals the identifying attributes of the account, at least one of which
should be considered the
-     * account's 'primary' identifying attribute, for example, a user id or username.
+     * @param principals  the identifying attributes of the account, at least one of which
should be considered the
+     *                    account's 'primary' identifying attribute, for example, a user
id or username.
      * @param credentials the credentials that verify identity for the account
-     * @param roleNames the names of the roles assigned to this account.
+     * @param roleNames   the names of the roles assigned to this account.
      * @param permissions the permissions assigned to this account directly (not those assigned
to any of the realms).
      */
     public SimpleAccount(PrincipalCollection principals, Object credentials, Set<String>
roleNames, Set<Permission> permissions) {
@@ -175,10 +177,6 @@
     /**
      * Returns the principals, aka the identifying attributes (username, user id, first name,
last name, etc) of this
      * Account.
-     * <p/>
-     * At least one of these attributes should be the account's 'primary' identifier, such
as a username or unique
-     * user id.  By convention, usually  the first principal (that is, <code>principals.iterator().next()</code>)
is the
-     * 'primary' one.
      *
      * @return all the principals, aka the identifying attributes, of this Account.
      */
@@ -189,10 +187,7 @@
     /**
      * Sets the principals, aka the identifying attributes (username, user id, first name,
last name, etc) of this
      * Account.
-     * <p/>
-     * At least one of these attributes should be the account's 'primary' identifier, such
as a username or unique
-     * user id.  By convention, usually the first principal (that is, <code>principals.iterator().next()</code>)
is the
-     * 'primary' one.
+     *
      * @param principals all the principals, aka the identifying attributes, of this Account.
      * @see Account#getPrincipals()
      */
@@ -224,6 +219,7 @@
 
     /**
      * Returns <code>this.authzInfo.getRoles();</code>
+     *
      * @return the Account's assigned roles.
      */
     public Collection<String> getRoles() {
@@ -263,6 +259,7 @@
     /**
      * Returns all String-based permissions assigned to this Account.  Simply delegates to
      * <code>this.authzInfo.getStringPermissions()</code>.
+     *
      * @return all String-based permissions assigned to this Account.
      */
     public Collection<String> getStringPermissions() {
@@ -272,6 +269,7 @@
     /**
      * Sets the String-based permissions assigned to this Account.  Simply delegates to
      * <code>this.authzInfo.setStringPermissions(permissions)</code>.
+     *
      * @param permissions all String-based permissions assigned to this Account.
      * @see org.apache.shiro.authc.Account#getStringPermissions()
      */
@@ -280,7 +278,8 @@
     }
 
     /**
-     * Assigns a String-based permission directly to this Account (not to any of its realms).
 
+     * Assigns a String-based permission directly to this Account (not to any of its realms).
+     *
      * @param permission the String-based permission to assign.
      */
     public void addStringPermission(String permission) {
@@ -289,6 +288,7 @@
 
     /**
      * Assigns one or more string-based permissions directly to this Account (not to any
of its realms).
+     *
      * @param permissions one or more String-based permissions to assign.
      */
     public void addStringPermissions(Collection<String> permissions) {
@@ -297,6 +297,7 @@
 
     /**
      * Returns all object-based permissions assigned directly to this Account (not any of
its realms).
+     *
      * @return all object-based permissions assigned directly to this Account (not any of
its realms).
      */
     public Collection<Permission> getObjectPermissions() {
@@ -305,6 +306,7 @@
 
     /**
      * Sets all object-based permissions assigned directly to this Account (not any of its
realms).
+     *
      * @param permissions the object-based permissions to assign directly to this Account.
      */
     public void setObjectPermissions(Set<Permission> permissions) {
@@ -313,6 +315,7 @@
 
     /**
      * Assigns an object-based permission directly to this Account (not any of its realms).
+     *
      * @param permission the object-based permission to assign directly to this Account (not
any of its realms).
      */
     public void addObjectPermission(Permission permission) {
@@ -321,6 +324,7 @@
 
     /**
      * Assigns one or more object-based permissions directly to this Account (not any of
its realms).
+     *
      * @param permissions one or more object-based permissions to assign directly to this
Account (not any of its realms).
      */
     public void addObjectPermissions(Collection<Permission> permissions) {
@@ -329,6 +333,7 @@
 
     /**
      * Returns <code>true</code> if this Account is locked and thus cannot be
used to login, <code>false</code> otherwise.
+     *
      * @return <code>true</code> if this Account is locked and thus cannot be
used to login, <code>false</code> otherwise.
      */
     public boolean isLocked() {
@@ -337,6 +342,7 @@
 
     /**
      * Sets whether or not the account is locked and can be used to login.
+     *
      * @param locked <code>true</code> if this Account is locked and thus cannot
be used to login, <code>false</code> otherwise.
      */
     public void setLocked(boolean locked) {
@@ -346,7 +352,8 @@
     /**
      * Returns whether or not the Account's credentials are expired.  This usually indicates
that the Subject or an application
      * administrator would need to change the credentials before the account could be used.
-     * @return whether or not the Account's credentials are expired.  
+     *
+     * @return whether or not the Account's credentials are expired.
      */
     public boolean isCredentialsExpired() {
         return credentialsExpired;
@@ -355,8 +362,9 @@
     /**
      * Sets whether or not the Account's credentials are expired.  A <code>true</code>
value indicates that the Subject
      * or application administrator would need to change their credentials before the account
could be used.
+     *
      * @param credentialsExpired <code>true</code> if this Account's credentials
are expired and need to be changed,
-     * <code>false</code> otherwise.
+     *                           <code>false</code> otherwise.
      */
     public void setCredentialsExpired(boolean credentialsExpired) {
         this.credentialsExpired = credentialsExpired;
@@ -368,7 +376,7 @@
      * <p/>
      * If the specified argument is also an instance of {@link SimpleAccount SimpleAccount},
the
      * {@link #isLocked()} and {@link #isCredentialsExpired()} attributes are merged (set
on this instance) as well
-     * (only if their values are <code>true</code>). 
+     * (only if their values are <code>true</code>).
      *
      * @param info the <code>AuthenticationInfo</code> to merge into this account.
      */
@@ -391,6 +399,7 @@
     /**
      * If the {@link #getPrincipals() principals} are not null, returns <code>principals.hashCode()</code>,
otherwise
      * returns 0 (zero).
+     *
      * @return <code>principals.hashCode()</code> if they are not null, 0 (zero)
otherwise.
      */
     public int hashCode() {
@@ -400,9 +409,10 @@
     /**
      * Returns <code>true</code> if the specified object is also a {@link SimpleAccount
SimpleAccount} and its
      * {@link #getPrincipals() principals} are equal to this object's <code>principals</code>,
<code>false</code> otherwise.
+     *
      * @param o the object to test for equality.
      * @return <code>true</code> if the specified object is also a {@link SimpleAccount
SimpleAccount} and its
-     * {@link #getPrincipals() principals} are equal to this object's <code>principals</code>,
<code>false</code> otherwise.
+     *         {@link #getPrincipals() principals} are equal to this object's <code>principals</code>,
<code>false</code> otherwise.
      */
     public boolean equals(Object o) {
         if (o == this) {
@@ -419,6 +429,7 @@
     /**
      * Returns {@link #getPrincipals() principals}.toString() if they are not null, otherwise
prints out the string
      * &quot;empty&quot;
+     *
      * @return the String representation of this Account object.
      */
     public String toString() {

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
Mon Sep 21 20:06:22 2009
@@ -496,7 +496,7 @@
 
         if (principals != null && !principals.isEmpty()) {
             if (log.isDebugEnabled()) {
-                log.debug("Logging out subject with primary id {}" + principals.iterator().next());
+                log.debug("Logging out subject with primary principal {}" + principals.getPrimaryPrincipal());
             }
             beforeLogout(principals);
             Authenticator authc = getAuthenticator();

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
Mon Sep 21 20:06:22 2009
@@ -625,8 +625,7 @@
      * <code>principals.{@link PrincipalCollection#fromRealm(String) fromRealm}({@link
#getName() getName()})</code>
      * call.</li>
      * <li>If the previous call does not result in any principals, attempt to get the
overall 'primary' principal
-     * from the PrincipalCollection via a <code>principals.{@link PrincipalCollection#asList()
asList()}.iterator().next()</code>
-     * call.</li>
+     * from the PrincipalCollection via {@link org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()}.</li>
      * <li>If there are no principals from that call (or the PrincipalCollection argument
was null to begin with),
      * return {@code null}</li>
      * </ul>
@@ -640,17 +639,13 @@
         if (principals == null || principals.isEmpty()) {
             return null;
         }
-        Object primary = null;
+        Object primary;
         Collection thisPrincipals = principals.fromRealm(getName());
         if (thisPrincipals != null && !thisPrincipals.isEmpty()) {
             primary = thisPrincipals.iterator().next();
         } else {
-            //no principals attributed to this particular realm.  Fall back to the 'master'
primary, that which
-            //is returned as the first from all principals:
-            Collection allPrincipals = principals.asList();
-            if (allPrincipals != null && !allPrincipals.isEmpty()) {
-                primary = allPrincipals.iterator().next();
-            }
+            //no principals attributed to this particular realm.  Fall back to the 'master'
primary:
+            primary = principals.getPrimaryPrincipal();
         }
         return primary;
     }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
Mon Sep 21 20:06:22 2009
@@ -138,7 +138,7 @@
 
     protected Object getPrimaryPrincipal(PrincipalCollection principals) {
         if (!CollectionUtils.isEmpty(principals)) {
-            return principals.iterator().next();
+            return principals.getPrimaryPrincipal();
         }
         return null;
     }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
Mon Sep 21 20:06:22 2009
@@ -28,16 +28,12 @@
  * just a security term for an identifying attribute, such as a username or user id or social
security number or
  * anything else that can be considered an 'identifying' attribute for a {@code Subject}.
  * <p/>
- * Note that by convention however, the 'first' principal returned from this collection is
considered to be the
- * Subject's <em>primary</em> principal used by the application, usually a user
ID or username, based on the
- * {@code Realm} implementation.  The 'first' principal is that which is returned by
- * {@link #asList() asList()}{@code .iterator().next()}.
- * <p/>
  * A PrincipalCollection organizes its internal principals based on the {@code Realm} where
they came from when the
  * Subject was first created.  To obtain the principal(s) for a specific Realm, see the {@link
#fromRealm} method.  You
  * can also see which realms contributed to this collection via the {@link #getRealmNames()
getRealmNames()} method.
  *
  * @author Les Hazlewood
+ * @see #getPrimaryPrincipal()
  * @see #fromRealm(String realmName)
  * @see #getRealmNames()
  * @since 0.9
@@ -45,8 +41,45 @@
 public interface PrincipalCollection extends Iterable, Serializable {
 
     /**
-     * Returns a single principal assignable from the specified type, or {@code null} if
there are none of the
-     * specified type.
+     * Returns the primary principal used to uniquely identify the owning account/Subject.
+     * <p/>
+     * The value is usually always a uniquely identifying attribute specific to the data
source that retrieved the
+     * account data.  Some examples:
+     * <ul>
+     * <li>a {@link java.util.UUID UUID}</li>
+     * <li>a {@code long} value such as a surrogate primary key in a relational database</li>
+     * <li>an LDAP UUID or static DN</li>
+     * <li>a String username unique across all user accounts</li>
+     * </ul>
+     * <h3>Multi-Realm Applications</h3>
+     * In a single-{@code Realm} application, typically there is only ever one unique principal
to retain and that
+     * is the value returned from this method.  However, in a multi-{@code Realm} application,
where the
+     * {@code PrincipalCollection} might retain principals across more than one realm, the
value returned from this
+     * method should be the single principal that uniquely identifies the subject for the
entire application.
+     * <p/>
+     * That value is of course application specific, but most applications will typically
choose one of the primary
+     * principals from one of the {@code Realm}s.
+     * <p/>
+     * Shiro's default implementations of this interface make this
+     * assumption by usually simply returning {@link #iterator()}.{@link java.util.Iterator#next()
next()}, which just
+     * returns the first returned principal obtained from the first consulted/configured
{@code Realm} during the
+     * authentication attempt.  This means in a multi-{@code Realm} application, {@code Realm}
configuraiton order
+     * matters if you want to retain this default heuristic.
+     * <p/>
+     * If this heuristic is not sufficient, most Shiro end-users will need to implement a
custom
+     * {@link org.apache.shiro.authc.pam.AuthenticationStrategy}.  An {@code AuthenticationStrategy}
has exact control
+     * over the {@link PrincipalCollection} returned at the end of an authentication attempt
via the
+     * <code>AuthenticationStrategy#{@link org.apache.shiro.authc.pam.AuthenticationStrategy#afterAllAttempts(org.apache.shiro.authc.AuthenticationToken,
org.apache.shiro.authc.AuthenticationInfo) afterAllAttempts}</code>
+     * implementation.
+     *
+     * @return the primary principal used to uniquely identify the owning account/Subject
+     * @since 1.0
+     */
+    Object getPrimaryPrincipal();
+
+    /**
+     * Returns the first discovered principal assignable from the specified type, or {@code
null} if there are none
+     * of the specified type.
      * <p/>
      * Note that this will return {@code null} if the 'owning' subject has not yet logged
in.
      *

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
Mon Sep 21 20:06:22 2009
@@ -18,15 +18,7 @@
  */
 package org.apache.shiro.subject;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 
 /**
@@ -74,6 +66,22 @@
         return principals;
     }
 
+    /**
+     * Returns the first available principal from any of the {@code Realm} principals, or
{@code null} if there are
+     * no principals yet.
+     * <p/>
+     * The 'first available principal' is interpreted as the principal that would be returned
by
+     * <code>{@link #iterator() iterator()}.{@link java.util.Iterator#next() next()}.</code>
+     *
+     * @inheritDoc
+     */
+    public Object getPrimaryPrincipal() {
+        if (isEmpty()) {
+            return null;
+        }
+        return iterator().next();
+    }
+
     public void add(Object principal, String realmName) {
         if (realmName == null) {
             throw new IllegalArgumentException("realmName argument cannot be null.");

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/Subject.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/Subject.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/Subject.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/Subject.java Mon Sep
21 20:06:22 2009
@@ -73,17 +73,11 @@
      * your application.  This implies that things like given names and family names are
usually poor candidates as
      * return values since they are rarely guaranteed to be unique.
      * <p/>
-     * Most single-Realm applications would return from this method a single unique principal
as noted above
-     * (for example a String username or Long user id, etc, etc).  Single-realm applications
represent the large
-     * majority of Shiro applications.
-     * <p/>
-     * However, in <em>multi</em>-Realm configurations, which are fully supported
by Shiro as well, it is
-     * possible that the return value encapsulates more than one principal.  Typically multi-realm
applications need to
-     * retain the unique principals for <em>each</em> Realm so subsequent security
checks against these Realms can
-     * utilize these multiple principals.  In these cases, the object returned could be a
Collection or any
-     * application-specific instance that encapsulates the principals.
+     * Most implementations will simply return
+     * <code>{@link #getPrincipals()}.{@link org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
getPrimaryPrincipal()}</code>
      *
-     * @return this Subject's application-specific identity.
+     * @return this Subject's application-specific unique identity.
+     * @see org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
      */
     Object getPrincipal();
 
@@ -93,20 +87,10 @@
      * The word &quot;principals&quot; is nothing more than a fancy security term
for identifying attributes associated
      * with a Subject, aka, application user.  For example, user id, a surname (family/last
name), given (first) name,
      * social security number, nickname, username, etc, are all examples of a principal.
-     * <p/>
-     * This method returns all of the principals associated with the Subject, and it is expected
that at least one of
-     * the principals contained within this collection represent an absolute unique identifier
for the application.
-     * User IDs, such a {@code Long} database primary key or UUID, or maybe a globally unique
username or email
-     * address are all good candidates for such a unique identifier.  Non-unique things,
such as surnames and
-     * given names, are often poor candidates.
-     * <p/>
-     * For convenience's sake, it is convention that the first principal in this collection
be the application's
-     * &quot;primary&quot; principal.  That is, {@code getPrincipals().iterator().next();}
would return this
-     * primary uniquely-identifying principal.  Most {@link #getPrincipal() getPrincipal()}
implementations will use
-     * this logic.
      *
      * @return all of this Subject's principals (identifying attributes).
      * @see #getPrincipal()
+     * @see org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
      */
     PrincipalCollection getPrincipals();
 

Modified: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/AuthorizingRealmTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/AuthorizingRealmTest.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/AuthorizingRealmTest.java
(original)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/AuthorizingRealmTest.java
Mon Sep 21 20:06:22 2009
@@ -86,7 +86,7 @@
         assertNotNull(info);
         assertTrue(realm.hasRole(info.getPrincipals(), ROLE));
 
-        Object principal = info.getPrincipals().iterator().next();
+        Object principal = info.getPrincipals().getPrimaryPrincipal();
         assertTrue(principal instanceof UserIdPrincipal);
 
         UsernamePrincipal usernamePrincipal = info.getPrincipals().oneByType(UsernamePrincipal.class);
@@ -114,7 +114,7 @@
         AuthenticationInfo info = realm.getAuthenticationInfo(new UsernamePasswordToken(USERNAME,
PASSWORD, localhost));
         assertNotNull(info);
         assertTrue(realm.hasRole(info.getPrincipals(), ROLE));
-        Object principal = info.getPrincipals().iterator().next();
+        Object principal = info.getPrincipals().getPrimaryPrincipal();
         assertTrue(principal instanceof UsernamePrincipal);
         assertEquals(USERNAME, ((UsernamePrincipal) principal).getUsername());
 

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java?rev=817392&r1=817391&r2=817392&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
(original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
Mon Sep 21 20:06:22 2009
@@ -25,7 +25,7 @@
 import org.apache.shiro.subject.SimplePrincipalCollection;
 import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
 import static org.easymock.EasyMock.*;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 import org.junit.Test;
 
 import javax.servlet.http.Cookie;
@@ -70,9 +70,15 @@
 
         expect(mockRequest.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY)).andReturn(null);
 
-        //The following base64 string was determined from the log output of the above test.
-        //This may have to change if the VM changes - not sure. L.H.
-        final String userPCBlowfishBase64 = "UwP13UzjVUceLBNWh+sYM01JWOSbBOwc1ZLySIws0IdnkcWeD/yWeH0eIycwHaI8MRKPyenBr76TL6F3P3FpTceMcJ+xDfwSqOgU/ZQLdvIOxlZxmT9RlUvKT6zopnQrSpdsCNaruG/Op/XEoJcdNLI9rJCCyMKN3em5wl8GrWTIzKS4hzHombGBEW4EPS9jv40HV4mIS2sUFXm5MlOptr99e1A6eKYxlLrldk2/yqw29nWohE0sIjO7tRF9mOAZUeC/Fem6K4S82LbXAJ6p0oNg3MP7dbFSkeeDF2CwFJvvi5xVrGyF0RnTzjwKZdTcvg4bx9ifQpKyPayQgsjCjd3pucJfBq1kuw/IyiPdSREnzWAEXOQi9o9II4jNvOJik+VI3QkwWdBBekzEKCACn8uvjlLKSiR8tCs9vbycs5N0FrODxMQ5FDvhV+rZLHtP/KP1puAwmeo=";
+        //The following base64 string was determined from the log output of the above 'onSuccessfulLogin'
test.
+        //This will have to change any time the PrincipalCollection implementation changes:
+        final String userPCBlowfishBase64 = "UwP13UzjVUceLBNWh+sYM01JWOSbBOwc1ZLySIws0Idnkc"
+
+                "WeD/yWeH0eIycwHaI8MRKPyenBr76EoLkEZnXSz4i27cTTUps5qOgU/ZQLdvIOxlZxmT9RlUvK"
+
+                "T6zopnQrSpdsCNaruG/Op/XEoJcdNLI9rJCCyMKN3em5wl8GrWTIzKS4hzHombGBEW4EPS9jv4"
+
+                "0HV4mIS2sUFXm5MlOptr99e1A6eKYxlLrldk2/yqw29nWohE0sIjO7tRF9mOAZUeC/Fem6K4S8"
+
+                "2LbXAJ6p0oNg3MP7dbFSkeeDF2CwFJvvi5xVrGyF0RnTzjwKZdTcvg4bx9ifQpKyPayQgsjCjd"
+
+                "3pucJfBq1kuw/IyiPdSREnzWAEXOQi9o9II4jNvOJik+VI3QkwWdBBekzEKCACn8uvjlLKSiR8"
+
+                "tCs9vbycs5N0FrODxMQ5FDvhV+rZLHtP/KP1puAwmeo=";
         Cookie[] cookies = new Cookie[]{
                 new Cookie(WebRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME, userPCBlowfishBase64)
         };



Mime
View raw message