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 module hunt.shiro.authc.SimpleAuthenticationInfo; 20 21 import hunt.shiro.authc.AuthenticationInfo; 22 import hunt.shiro.authc.MergableAuthenticationInfo; 23 import hunt.shiro.authc.SaltedAuthenticationInfo; 24 import hunt.shiro.subject.MutablePrincipalCollection; 25 import hunt.shiro.subject.PrincipalCollection; 26 import hunt.shiro.subject.SimplePrincipalCollection; 27 import hunt.shiro.util.ByteSource; 28 29 30 import hunt.collection; 31 import hunt.collection.HashSet; 32 import hunt.collection.Set; 33 34 35 /** 36 * Simple implementation of the {@link hunt.shiro.authc.MergableAuthenticationInfo} interface that holds the principals and 37 * credentials. 38 * 39 * @see hunt.shiro.realm.AuthenticatingRealm 40 */ 41 class SimpleAuthenticationInfo : MergableAuthenticationInfo, SaltedAuthenticationInfo { 42 43 /** 44 * The principals identifying the account associated with this AuthenticationInfo instance. 45 */ 46 protected PrincipalCollection principals; 47 48 /** 49 * The credentials verifying the account principals. 50 */ 51 protected Object credentials; 52 53 /** 54 * Any salt used in hashing the credentials. 55 * 56 */ 57 protected ByteSource credentialsSalt; 58 59 /** 60 * Default no-argument constructor. 61 */ 62 this() { 63 } 64 65 /** 66 * Constructor that takes in a single 'primary' principal of the account and its corresponding credentials, 67 * associated with the specified realm. 68 * <p/> 69 * This is a convenience constructor and will construct a {@link PrincipalCollection PrincipalCollection} based 70 * on the {@code principal} and {@code realmName} argument. 71 * 72 * @param principal the 'primary' principal associated with the specified realm. 73 * @param credentials the credentials that verify the given principal. 74 * @param realmName the realm from where the principal and credentials were acquired. 75 */ 76 this(Object principal, Object credentials, string realmName) { 77 this.principals = new SimplePrincipalCollection(principal, realmName); 78 this.credentials = credentials; 79 } 80 81 /** 82 * Constructor that takes in a single 'primary' principal of the account, its corresponding hashed credentials, 83 * the salt used to hash the credentials, and the name of the realm to associate with the principals. 84 * <p/> 85 * This is a convenience constructor and will construct a {@link PrincipalCollection PrincipalCollection} based 86 * on the <code>principal</code> and <code>realmName</code> argument. 87 * 88 * @param principal the 'primary' principal associated with the specified realm. 89 * @param hashedCredentials the hashed credentials that verify the given principal. 90 * @param credentialsSalt the salt used when hashing the given hashedCredentials 91 * @param realmName the realm from where the principal and credentials were acquired. 92 * @see hunt.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher 93 */ 94 this(Object principal, Object hashedCredentials, ByteSource credentialsSalt, string realmName) { 95 this.principals = new SimplePrincipalCollection(principal, realmName); 96 this.credentials = hashedCredentials; 97 this.credentialsSalt = credentialsSalt; 98 } 99 100 /** 101 * Constructor that takes in an account's identifying principal(s) and its corresponding credentials that verify 102 * the principals. 103 * 104 * @param principals a Realm's account's identifying principal(s) 105 * @param credentials the accounts corresponding principals that verify the principals. 106 */ 107 this(PrincipalCollection principals, Object credentials) { 108 this.principals = new SimplePrincipalCollection(principals); 109 this.credentials = credentials; 110 } 111 112 /** 113 * Constructor that takes in an account's identifying principal(s), hashed credentials used to verify the 114 * principals, and the salt used when hashing the credentials. 115 * 116 * @param principals a Realm's account's identifying principal(s) 117 * @param hashedCredentials the hashed credentials that verify the principals. 118 * @param credentialsSalt the salt used when hashing the hashedCredentials. 119 * @see hunt.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher 120 */ 121 this(PrincipalCollection principals, Object hashedCredentials, ByteSource credentialsSalt) { 122 this.principals = new SimplePrincipalCollection(principals); 123 this.credentials = hashedCredentials; 124 this.credentialsSalt = credentialsSalt; 125 } 126 127 128 PrincipalCollection getPrincipals() @trusted nothrow { 129 return principals; 130 } 131 132 /** 133 * Sets the identifying principal(s) represented by this instance. 134 * 135 * @param principals the indentifying attributes of the corresponding Realm account. 136 */ 137 void setPrincipals(PrincipalCollection principals) { 138 this.principals = principals; 139 } 140 141 Object getCredentials() { 142 return credentials; 143 } 144 145 /** 146 * Sets the credentials that verify the principals/identity of the associated Realm account. 147 * 148 * @param credentials attribute(s) that verify the account's identity/principals, such as a password or private key. 149 */ 150 void setCredentials(Object credentials) { 151 this.credentials = credentials; 152 } 153 154 /** 155 * Returns the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not 156 * hashed at all. 157 * <p/> 158 * Note that this attribute is <em>NOT</em> handled in the 159 * {@link #merge(AuthenticationInfo) merge} method - a hash salt is only useful within a single realm (as each 160 * realm will perform it's own Credentials Matching logic), and once finished in that realm, Shiro has no further 161 * use for salts. Therefore it doesn't make sense to 'merge' salts in a multi-realm scenario. 162 * 163 * @return the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not 164 * hashed at all. 165 */ 166 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 */ 182 void setCredentialsSalt(ByteSource salt) { 183 this.credentialsSalt = salt; 184 } 185 186 /** 187 * Takes the specified <code>info</code> argument and adds its principals and credentials into this instance. 188 * 189 * @param info the <code>AuthenticationInfo</code> to add into this instance. 190 */ 191 192 void merge(AuthenticationInfo info) { 193 if (info is null || info.getPrincipals() is null || info.getPrincipals().isEmpty()) { 194 return; 195 } 196 197 if (this.principals is null) { 198 this.principals = info.getPrincipals(); 199 } else { 200 auto principalsCast = cast(MutablePrincipalCollection)this.principals; 201 if (principalsCast is null) { 202 this.principals = new SimplePrincipalCollection(this.principals); 203 } 204 principalsCast.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 auto infoCast = cast(SaltedAuthenticationInfo)info; 214 if (this.credentialsSalt is null && infoCast !is null) { 215 this.credentialsSalt = infoCast.getCredentialsSalt(); 216 } 217 218 Object thisCredentials = getCredentials(); 219 Object otherCredentials = info.getCredentials(); 220 221 if (otherCredentials is null) { 222 return; 223 } 224 225 if (thisCredentials is null) { 226 this.credentials = otherCredentials; 227 return; 228 } 229 auto thisCredentialsCast = cast(Collection!Object) thisCredentials; 230 if (thisCredentialsCast is null) { 231 Set!Object newSet = new HashSet!Object(); 232 newSet.add(thisCredentials); 233 setCredentials(cast(Object)newSet); 234 } 235 236 // At this point, the credentials should be a collection 237 Collection!Object credentialCollection = cast(Collection!Object)getCredentials(); 238 auto otherCredentialsCast = cast(Collection!Object)otherCredentials; 239 if (otherCredentialsCast !is null) { 240 credentialCollection.addAll(otherCredentialsCast); 241 } else { 242 credentialCollection.add(otherCredentials); 243 } 244 } 245 246 /** 247 * Returns <code>true</code> if the Object argument is an <code>instanceof SimpleAuthenticationInfo</code> and 248 * its {@link #getPrincipals() principals} are equal to this instance's principals, <code>false</code> otherwise. 249 * 250 * @param o the object to compare for equality. 251 * @return <code>true</code> if the Object argument is an <code>instanceof SimpleAuthenticationInfo</code> and 252 * its {@link #getPrincipals() principals} are equal to this instance's principals, <code>false</code> otherwise. 253 */ 254 override bool opEquals(Object o) { 255 if (this == o) return true; 256 auto oCast = cast(SimpleAuthenticationInfo)o; 257 if (oCast is null) return false; 258 259 SimpleAuthenticationInfo that = oCast; 260 261 //noinspection RedundantIfStatement 262 if (principals !is null ? principals != that.principals : that.principals !is null) return false; 263 264 return true; 265 } 266 267 /** 268 * Returns the hashcode of the internal {@link #getPrincipals() principals} instance. 269 * 270 * @return the hashcode of the internal {@link #getPrincipals() principals} instance. 271 */ 272 override size_t toHash() @trusted nothrow { 273 return (principals !is null ? (cast(Object)principals).toHash() : 0); 274 } 275 276 /** 277 * Simple implementation that merely returns <code>{@link #getPrincipals() principals}.toString()</code> 278 * 279 * @return <code>{@link #getPrincipals() principals}.toString()</code> 280 */ 281 override string toString() { 282 return (cast(Object) principals).toString(); 283 } 284 285 }