c# - Dependency Injection ASP.NET : Unaware about the dependencies until Runtime -
i using asp.net core , using di build hashing functionality. since don't know type of hashing used @ stage (we storing in persistent storage).
the icrypto contract
public interface icrypto { string hashpassword(string plainpassword); bool verifyhashedpassword(string hashedpassword, string providedpassword); }
i have several implementations of icrypto , wrap other libraries , provide implementation of icrypto signatures. example:
- cryptomd5
- cryptosha1
- cytpoother
now, in userservice inject icyrpto hash passwords example:
public class userservice { icrypto _crypto; public userservice(icrypto crypto) { _crypto = crypto; } public bool login (string username, string password) { //code omitted var hash = _crypto.hashpassword(password); } }
adding dependencies container in startup class
//get encryption type stored in cache, db or somewhere var cryptotype = //get param if (cryptotype = "sha1") { services.addtransient<icrypto, cryptosha1>(); } else if (cryptotype = "md5") { services.addtransient<icrypto, cryptomd5>(); }
i looking way according best practices , reflect steves has mentioned.
in case cryptotype
value database constant during lifetime of application (which means, if want change it, you're fine restarting application), means cryptotype configuration value , can wire application described:
var cryptotype = //get param if (cryptotype = "sha1") { services.addtransient<icrypto, cryptosha1>(); } else if (cryptotype = "md5") { services.addtransient<icrypto, cryptomd5>(); }
if need swap implementations dynamically (which find unlikely in specific case, let's assume sake of argument), solution implement proxy , wrap real implementations. example:
public interface databasecryptoselectorproxy : icrypto { private readonly cryptosha1 sha; private readonly cryptomd5 md5; public databasecryptoselectorproxy(cryptosha1 sha, cryptomd5 md5) { this.sha = sha; this.md5 = md5; } public string hashpassword(string plainpassword) => getcrypto().hashpasswords(plainpassword); public bool verifyhashedpassword(string hashedpassword, string providedpassword) => getcrypto().verifyhashedpassword(hashedpassword, providedpassword); private icrypto getcrypto() { var cryptotype = // param if (cryptotype = "sha1") return this.sha; if (cryptotype = "md5") return this.md5; throw new invalidoperationexception("unknown cryptotype: " + cryptotype); } }
this proxy has few clear advantages:
- it makes consumers of
icrypto
oblivious fact complex dispatching happening based on data database. - it prevents having execute query during object graph construction, since make process unreliable , hard verify.
some notes though design around password hashing security perspective. don't see strong reason switch crypto methods way doing, , not switch algorithms md5. instead, advise using pbkdf2 in form of rfc2898derivebytes. example of how can shown here. concatenating number of hash iterations hashed password (for instance doing + "|" + iterations
), can later on increase number of used iterations keeping industry standard , allows automatically rehash user's password on login if number if detect number of used iterations old value.
additionally, if think ever need move away pbkdf2, can prefix hash used algorithm, way can again use proxy passes hashed password on right implementation based on algorithm-prefix. storing algorithm in password hash in database, can migrate transparently without having convert existing passwords @ once (which impossible, because can't decrypt hashed password).
Comments
Post a Comment