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