001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.authc;
020    
021    import org.apache.shiro.subject.MutablePrincipalCollection;
022    import org.apache.shiro.subject.PrincipalCollection;
023    import org.apache.shiro.subject.SimplePrincipalCollection;
024    import org.apache.shiro.util.ByteSource;
025    
026    import java.util.Collection;
027    import java.util.HashSet;
028    import java.util.Set;
029    
030    
031    /**
032     * Simple implementation of the {@link org.apache.shiro.authc.MergableAuthenticationInfo} interface that holds the principals and
033     * credentials.
034     *
035     * @see org.apache.shiro.realm.AuthenticatingRealm
036     * @since 0.9
037     */
038    public class SimpleAuthenticationInfo implements MergableAuthenticationInfo, SaltedAuthenticationInfo {
039    
040        /**
041         * The principals identifying the account associated with this AuthenticationInfo instance.
042         */
043        protected PrincipalCollection principals;
044        /**
045         * The credentials verifying the account principals.
046         */
047        protected Object credentials;
048    
049        /**
050         * Any salt used in hashing the credentials.
051         *
052         * @since 1.1
053         */
054        protected ByteSource credentialsSalt;
055    
056        /**
057         * Default no-argument constructor.
058         */
059        public SimpleAuthenticationInfo() {
060        }
061    
062        /**
063         * Constructor that takes in a single 'primary' principal of the account and its corresponding credentials,
064         * associated with the specified realm.
065         * <p/>
066         * This is a convenience constructor and will construct a {@link PrincipalCollection PrincipalCollection} based
067         * on the {@code principal} and {@code realmName} argument.
068         *
069         * @param principal   the 'primary' principal associated with the specified realm.
070         * @param credentials the credentials that verify the given principal.
071         * @param realmName   the realm from where the principal and credentials were acquired.
072         */
073        public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName) {
074            this.principals = new SimplePrincipalCollection(principal, realmName);
075            this.credentials = credentials;
076        }
077    
078        /**
079         * Constructor that takes in a single 'primary' principal of the account, its corresponding hashed credentials,
080         * the salt used to hash the credentials, and the name of the realm to associate with the principals.
081         * <p/>
082         * This is a convenience constructor and will construct a {@link PrincipalCollection PrincipalCollection} based
083         * on the <code>principal</code> and <code>realmName</code> argument.
084         *
085         * @param principal         the 'primary' principal associated with the specified realm.
086         * @param hashedCredentials the hashed credentials that verify the given principal.
087         * @param credentialsSalt   the salt used when hashing the given hashedCredentials
088         * @param realmName         the realm from where the principal and credentials were acquired.
089         * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
090         * @since 1.1
091         */
092        public SimpleAuthenticationInfo(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
093            this.principals = new SimplePrincipalCollection(principal, realmName);
094            this.credentials = hashedCredentials;
095            this.credentialsSalt = credentialsSalt;
096        }
097    
098        /**
099         * Constructor that takes in an account's identifying principal(s) and its corresponding credentials that verify
100         * the principals.
101         *
102         * @param principals  a Realm's account's identifying principal(s)
103         * @param credentials the accounts corresponding principals that verify the principals.
104         */
105        public SimpleAuthenticationInfo(PrincipalCollection principals, Object credentials) {
106            this.principals = new SimplePrincipalCollection(principals);
107            this.credentials = credentials;
108        }
109    
110        /**
111         * Constructor that takes in an account's identifying principal(s), hashed credentials used to verify the
112         * principals, and the salt used when hashing the credentials.
113         *
114         * @param principals        a Realm's account's identifying principal(s)
115         * @param hashedCredentials the hashed credentials that verify the principals.
116         * @param credentialsSalt   the salt used when hashing the hashedCredentials.
117         * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
118         * @since 1.1
119         */
120        public SimpleAuthenticationInfo(PrincipalCollection principals, Object hashedCredentials, ByteSource credentialsSalt) {
121            this.principals = new SimplePrincipalCollection(principals);
122            this.credentials = hashedCredentials;
123            this.credentialsSalt = credentialsSalt;
124        }
125    
126    
127        public PrincipalCollection getPrincipals() {
128            return principals;
129        }
130    
131        /**
132         * Sets the identifying principal(s) represented by this instance.
133         *
134         * @param principals the indentifying attributes of the corresponding Realm account.
135         */
136        public void setPrincipals(PrincipalCollection principals) {
137            this.principals = principals;
138        }
139    
140        public Object getCredentials() {
141            return credentials;
142        }
143    
144        /**
145         * Sets the credentials that verify the principals/identity of the associated Realm account.
146         *
147         * @param credentials attribute(s) that verify the account's identity/principals, such as a password or private key.
148         */
149        public void setCredentials(Object credentials) {
150            this.credentials = credentials;
151        }
152    
153        /**
154         * Returns the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not
155         * hashed at all.
156         * <p/>
157         * Note that this attribute is <em>NOT</em> handled in the
158         * {@link #merge(AuthenticationInfo) merge} method - a hash salt is only useful within a single realm (as each
159         * realm will perform it's own Credentials Matching logic), and once finished in that realm, Shiro has no further
160         * use for salts.  Therefore it doesn't make sense to 'merge' salts in a multi-realm scenario.
161         *
162         * @return the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not
163         *         hashed at all.
164         * @since 1.1
165         */
166        public ByteSource getCredentialsSalt() {
167            return credentialsSalt;
168        }
169    
170        /**
171         * Sets the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not
172         * hashed at all.
173         * <p/>
174         * Note that this attribute is <em>NOT</em> handled in the
175         * {@link #merge(AuthenticationInfo) merge} method - a hash salt is only useful within a single realm (as each
176         * realm will perform it's own Credentials Matching logic), and once finished in that realm, Shiro has no further
177         * use for salts.  Therefore it doesn't make sense to 'merge' salts in a multi-realm scenario.
178         *
179         * @param salt the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not
180         *             hashed at all.
181         * @since 1.1
182         */
183        public void setCredentialsSalt(ByteSource salt) {
184            this.credentialsSalt = salt;
185        }
186    
187        /**
188         * Takes the specified <code>info</code> argument and adds its principals and credentials into this instance.
189         *
190         * @param info the <code>AuthenticationInfo</code> to add into this instance.
191         */
192        @SuppressWarnings("unchecked")
193        public void merge(AuthenticationInfo info) {
194            if (info == null || info.getPrincipals() == null || info.getPrincipals().isEmpty()) {
195                return;
196            }
197    
198            if (this.principals == null) {
199                this.principals = info.getPrincipals();
200            } else {
201                if (!(this.principals instanceof MutablePrincipalCollection)) {
202                    this.principals = new SimplePrincipalCollection(this.principals);
203                }
204                ((MutablePrincipalCollection) this.principals).addAll(info.getPrincipals());
205            }
206    
207            //only mess with a salt value if we don't have one yet.  It doesn't make sense
208            //to merge salt values from different realms because a salt is used only within
209            //the realm's credential matching process.  But if the current instance's salt
210            //is null, then it can't hurt to pull in a non-null value if one exists.
211            //
212            //since 1.1:
213            if (this.credentialsSalt == null && info instanceof SaltedAuthenticationInfo) {
214                this.credentialsSalt = ((SaltedAuthenticationInfo) info).getCredentialsSalt();
215            }
216    
217            Object thisCredentials = getCredentials();
218            Object otherCredentials = info.getCredentials();
219    
220            if (otherCredentials == null) {
221                return;
222            }
223    
224            if (thisCredentials == null) {
225                this.credentials = otherCredentials;
226                return;
227            }
228    
229            if (!(thisCredentials instanceof Collection)) {
230                Set newSet = new HashSet();
231                newSet.add(thisCredentials);
232                setCredentials(newSet);
233            }
234    
235            // At this point, the credentials should be a collection
236            Collection credentialCollection = (Collection) getCredentials();
237            if (otherCredentials instanceof Collection) {
238                credentialCollection.addAll((Collection) otherCredentials);
239            } else {
240                credentialCollection.add(otherCredentials);
241            }
242        }
243    
244        /**
245         * Returns <code>true</code> if the Object argument is an <code>instanceof SimpleAuthenticationInfo</code> and
246         * its {@link #getPrincipals() principals} are equal to this instance's principals, <code>false</code> otherwise.
247         *
248         * @param o the object to compare for equality.
249         * @return <code>true</code> if the Object argument is an <code>instanceof SimpleAuthenticationInfo</code> and
250         *         its {@link #getPrincipals() principals} are equal to this instance's principals, <code>false</code> otherwise.
251         */
252        public boolean equals(Object o) {
253            if (this == o) return true;
254            if (!(o instanceof SimpleAuthenticationInfo)) return false;
255    
256            SimpleAuthenticationInfo that = (SimpleAuthenticationInfo) o;
257    
258            //noinspection RedundantIfStatement
259            if (principals != null ? !principals.equals(that.principals) : that.principals != null) return false;
260    
261            return true;
262        }
263    
264        /**
265         * Returns the hashcode of the internal {@link #getPrincipals() principals} instance.
266         *
267         * @return the hashcode of the internal {@link #getPrincipals() principals} instance.
268         */
269        public int hashCode() {
270            return (principals != null ? principals.hashCode() : 0);
271        }
272    
273        /**
274         * Simple implementation that merely returns <code>{@link #getPrincipals() principals}.toString()</code>
275         *
276         * @return <code>{@link #getPrincipals() principals}.toString()</code>
277         */
278        public String toString() {
279            return principals.toString();
280        }
281    
282    }