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.subject.MutablePrincipalCollection; 022import org.apache.shiro.subject.PrincipalCollection; 023import org.apache.shiro.subject.SimplePrincipalCollection; 024import org.apache.shiro.util.ByteSource; 025 026import java.util.Collection; 027import java.util.HashSet; 028import 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 */ 038public 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}