1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.shiro.authc;
20
21 import org.apache.shiro.subject.MutablePrincipalCollection;
22 import org.apache.shiro.subject.PrincipalCollection;
23 import org.apache.shiro.subject.SimplePrincipalCollection;
24 import org.apache.shiro.util.ByteSource;
25
26 import java.util.Collection;
27 import java.util.HashSet;
28 import java.util.Set;
29
30
31 /**
32 * Simple implementation of the {@link org.apache.shiro.authc.MergableAuthenticationInfo} interface that holds the principals and
33 * credentials.
34 *
35 * @see org.apache.shiro.realm.AuthenticatingRealm
36 * @since 0.9
37 */
38 public class SimpleAuthenticationInfo implements MergableAuthenticationInfo, SaltedAuthenticationInfo {
39
40 /**
41 * The principals identifying the account associated with this AuthenticationInfo instance.
42 */
43 protected PrincipalCollection principals;
44 /**
45 * The credentials verifying the account principals.
46 */
47 protected Object credentials;
48
49 /**
50 * Any salt used in hashing the credentials.
51 *
52 * @since 1.1
53 */
54 protected ByteSource credentialsSalt;
55
56 /**
57 * Default no-argument constructor.
58 */
59 public SimpleAuthenticationInfo() {
60 }
61
62 /**
63 * Constructor that takes in a single 'primary' principal of the account and its corresponding credentials,
64 * associated with the specified realm.
65 * <p/>
66 * This is a convenience constructor and will construct a {@link PrincipalCollection PrincipalCollection} based
67 * on the {@code principal} and {@code realmName} argument.
68 *
69 * @param principal the 'primary' principal associated with the specified realm.
70 * @param credentials the credentials that verify the given principal.
71 * @param realmName the realm from where the principal and credentials were acquired.
72 */
73 public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName) {
74 this.principals = new SimplePrincipalCollection(principal, realmName);
75 this.credentials = credentials;
76 }
77
78 /**
79 * Constructor that takes in a single 'primary' principal of the account, its corresponding hashed credentials,
80 * the salt used to hash the credentials, and the name of the realm to associate with the principals.
81 * <p/>
82 * This is a convenience constructor and will construct a {@link PrincipalCollection PrincipalCollection} based
83 * on the <code>principal</code> and <code>realmName</code> argument.
84 *
85 * @param principal the 'primary' principal associated with the specified realm.
86 * @param hashedCredentials the hashed credentials that verify the given principal.
87 * @param credentialsSalt the salt used when hashing the given hashedCredentials
88 * @param realmName the realm from where the principal and credentials were acquired.
89 * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher
90 * @since 1.1
91 */
92 public SimpleAuthenticationInfo(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
93 this.principals = new SimplePrincipalCollection(principal, realmName);
94 this.credentials = hashedCredentials;
95 this.credentialsSalt = credentialsSalt;
96 }
97
98 /**
99 * 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 }