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 }