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.credential.PasswordMatcher; 20 21 import hunt.shiro.authc.credential.CredentialsMatcher; 22 import hunt.shiro.authc.credential.DefaultPasswordService; 23 import hunt.shiro.authc.credential.PasswordService; 24 import hunt.shiro.authc.credential.HashingPasswordService; 25 26 import hunt.shiro.authc.AuthenticationInfo; 27 import hunt.shiro.authc.AuthenticationToken; 28 import hunt.shiro.crypto.hash.Hash; 29 30 import hunt.Exceptions; 31 import hunt.String; 32 33 34 /** 35 * A {@link CredentialsMatcher} that employs best-practices comparisons for hashed text passwords. 36 * <p/> 37 * This implementation delegates to an internal {@link PasswordService} to perform the actual password 38 * comparison. This class is essentially a bridge between the generic CredentialsMatcher interface and the 39 * more specific {@code PasswordService} component. 40 * 41 */ 42 class PasswordMatcher : CredentialsMatcher { 43 44 private PasswordService passwordService; 45 46 this() { 47 this.passwordService = new DefaultPasswordService(); 48 } 49 50 bool doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { 51 52 // PasswordService service = ensurePasswordService(); 53 54 // Object submittedPassword = getSubmittedPassword(token); 55 // Object storedCredentials = getStoredPassword(info); 56 // assertStoredCredentialsType(storedCredentials); 57 // auto storedCredentialsCast = cast(Hash) storedCredentials; 58 // if (storedCredentialsCast !is null) { 59 // Hash hashedPassword = storedCredentialsCast; 60 // HashingPasswordService hashingService = assertHashingPasswordService(service); 61 // return hashingService.passwordsMatch(submittedPassword, hashedPassword); 62 // } 63 // //otherwise they are a string (asserted in the 'assertStoredCredentialsType' method call above): 64 // string formatted = (cast(String)storedCredentials).value; 65 // return passwordService.passwordsMatch(submittedPassword, formatted); 66 implementationMissing(false); 67 return false; 68 } 69 70 private HashingPasswordService assertHashingPasswordService(PasswordService service) { 71 auto serviceCast = cast(HashingPasswordService)service; 72 if (serviceCast !is null) { 73 return serviceCast; 74 } 75 string msg = "AuthenticationInfo's stored credentials are a Hash instance, but the " ~ 76 "configured passwordService is not a " ~ 77 "HashingPasswordService instance. This is required to perform Hash " ~ 78 "object password comparisons."; 79 throw new IllegalStateException(msg); 80 } 81 82 private PasswordService ensurePasswordService() { 83 PasswordService service = getPasswordService(); 84 if (service is null) { 85 string msg = "Required PasswordService has not been configured."; 86 throw new IllegalStateException(msg); 87 } 88 return service; 89 } 90 91 protected char[] getSubmittedPassword(AuthenticationToken token) { 92 return token !is null ? token.getCredentials() : null; 93 } 94 95 private void assertStoredCredentialsType(Object credentials) { 96 auto credentialsCast = cast(String)credentials; 97 auto credentialsCast2 = cast(Hash)credentials; 98 if (credentialsCast !is null || credentialsCast2 !is null) { 99 return; 100 } 101 102 string msg = "Stored account credentials are expected to be either a " ~ 103 "Hash instance or a formatted hash string."; 104 throw new IllegalArgumentException(msg); 105 } 106 107 protected Object getStoredPassword(AuthenticationInfo storedAccountInfo) { 108 Object stored = storedAccountInfo !is null ? storedAccountInfo.getCredentials() : null; 109 //fix for https://issues.apache.org/jira/browse/SHIRO-363 110 // if (stored instanceof[] char) { 111 // stored = new string((char[])stored); 112 // } 113 return stored; 114 } 115 116 PasswordService getPasswordService() { 117 return passwordService; 118 } 119 120 void setPasswordService(PasswordService passwordService) { 121 this.passwordService = passwordService; 122 } 123 }