c# - Customizing ASP.NET Membership Provider further than normal -
i'm trying build web app using of out-of-the-box asp.net security can. got , running pretty using default patterns i'm trying make simple modification , getting sorts of confused. basically, i'm trying use generic userid (a stringified guid, instance) instead of username primary key user account. googling yields many threads on how inherit membershipprovider assuming you're overriding same method signatures ::createuser(string username, string password, ...). i'm kind of lost because don't know event raised causes ::createuser() called, nor method/class override in order change how it's called.
yes, know can "pretend" username userid in particular scenario i'd understand how works in case want make addition mods in future.
also, i'm trying customize info stored in authorization cookie think i've got handle on that. of relevant code in current half-baked condition shown below. thanks.
mymembershipprovider.cs
namespace myorg.myapp.infrastructure { public class myappmembershipprovider : membershipprovider { int minpasswordlength = myorg.myapp.common.config.minpasswordlength; public override membershipuser createuser(string username, string password, string email, string passwordquestion, string passwordanswer, bool isapproved, object provideruserkey, out membershipcreatestatus status) { /* want switch on uses userid instead of username */ user user = null; using (db db = new db()) { datetime creationdate = datetime.utcnow; user = new user() { username = username, email = email, pwd = myorg.utilities.misc.passwordhash.createhash(password) }; int recadded = db.insertuser(user); if (recadded > 0) { status = membershipcreatestatus.success; } else { status = membershipcreatestatus.userrejected; } } return getmembershipuserfromuser(user); } public override membershipuser getuser(string username, bool userisonline) { /* want switch on uses userid instead of username */ user user = null; using (db db = new db()) { user = db.getuser(username); } return getmembershipuserfromuser(user); } public override bool changepassword(string username, string oldpassword, string newpassword) { /* want switch on uses userid instead of username */ user user = null; using (db db = new db()) user = db.getuser(username); bool result = passwordhash.validatepassword(oldpassword, user.pwd); if (result) { user.pwd = utilities.misc.passwordhash.createhash(newpassword); user.lastpwdchange = datetime.utcnow; using (db db = new db()) db.updateuser(user); } return result; } public static bool validateuser(string username, string password, out string userid) { /* want switch on uses userid instead of username */ userid = null; using (db db = new db()) { user user = db.getuserbyusername(username); if (user == null) return false; bool result = myorg.utilities.misc.passwordhash.validatepassword(password, user.pwd); if (result) { user.failedpwdattemptcount = 0; user.failedpwdanswerattemptcount = 0; user.lastlogin = datetime.utcnow; userid = user.id; } else { user.failedpwdattemptcount++; user.failedpwdattemptwindowstart = datetime.utcnow; } db.updateuser(user); return result; } } private membershipuser getmembershipuserfromuser(user user) { return new membershipuser( "myappmembershipprovider", user.username, "dunno", user.email, user.pwdquestion, user.comment, user.isapproved, user.islockedout, user.created, user.lastlogin, user.lastactivity, user.lastpwdchange, user.lastlockedout); } public override int minrequiredpasswordlength { { return minpasswordlength; } } /* other inherited methods not implemented*/ } }
accountcontroller.cs
namespace myorg.myapp.controllers { public class accountcontroller : basecontroller { public actionresult logon() { return view(); } [httppost] public actionresult logon(formcollection form) { string username = form["username"]; string password = form["password"]; bool rememberme = form["rememberme"] != null; string returnurl = form["returnurl"]; string userid; if (myappmembershipprovider.validateuser(username, password, out userid)) { customprincipalserializemodel serializemodel = new customprincipalserializemodel(); serializemodel.userid = userid; serializemodel.username = username; system.web.script.serialization.javascriptserializer serializer = new system.web.script.serialization.javascriptserializer(); string userdata = serializer.serialize(serializemodel); formsauthenticationticket authticket = new formsauthenticationticket( 1, userid, datetime.now, datetime.now.addminutes(15), false, userdata); string encticket = formsauthentication.encrypt(authticket); httpcookie facookie = new httpcookie(formsauthentication.formscookiename, encticket); response.cookies.add(facookie); return redirecttoaction("index", "home"); } else { viewbag.validationmsg = "the user name or password provided incorrect."; } // if got far, failed, redisplay form viewbag.username = username; return view(); } public actionresult logoff() { formsauthentication.signout(); return redirecttoaction("index", "home"); } public actionresult details() { registermodel model = new registermodel(); user user; userprofile profile; using (db db = new db()) { user = db.getuser(user.userid); profile = db.getuserprofile(user.userid); } model.username = user.username; model.email = user.email; model.zip = profile.get(userprofile.properties.zip); return view(model); } public actionresult edit() { registermodel model = new registermodel(); model = null; user user; userprofile profile; using (db db = new db()) { user = db.getuser(user.userid); profile = db.getuserprofile(user.userid); } model.username = user.username; model.email = user.email; model.zip = profile.get(userprofile.properties.zip); return view(model); } [httppost] public actionresult edit(registermodel model) { userprofile profile = new userprofile(); profile.userid = model.username; profile.set(userprofile.properties.zip, model.zip); using (db db = new db()) { user user = db.getuser(model.username); user.email = model.email; db.updateuser(user); db.updateuserprofile(profile); } return redirecttoaction("index", "home"); } public actionresult register() { registermodel m = new registermodel(); return view(m); } [httppost] public actionresult register(registermodel model) { using (db db = new db()) { // check unique username if (db.getuser(model.username) != null) { viewbag.validationmsg = string.format("the username '{0}' taken. please choose another.", model.username); return view(); } membership.createuser(model.username, model.password, model.email); userprofile profile = new userprofile(); profile.userid = model.username; profile.set(userprofile.properties.zip, model.zip); db.insertuserprofile(profile); string confirmationcode = guid.newguid().tostring(); db.insertconfirmationcode(model.username, confirmationcode); // send email w/ confirmation code infrastructure.accountconfirmationemail email = new infrastructure.accountconfirmationemail( model.email, model.username, confirmationcode ); email.send(); } return view("confirmationemailsent"); } public actionresult confirm(string username, string code) { viewbag.username = username; viewbag.code = code; return view(); } [httppost] public actionresult confirm(string username, string code, string password) { string storedcode = null; using (db db = new db()) storedcode = db.getconfirmationcode(username); if (storedcode == null) { // username not found in confirmation_codes return view("confirmationcodenotfound"); } else { if (code == storedcode) { if (membership.validateuser(username, password)) { using (db db = new db()) { user user = db.getuser(username); user.isconfirmed = true; db.updateuser(user); db.deleteconfirmationcode(username); formsauthentication.setauthcookie(username, false); return redirecttoaction("index", "home"); } } else { viewbag.username = username; viewbag.code = code; viewbag.validationmsg = "incorrect password"; return view(); } } else { return view("confirmationcodenotfound"); } } } [authorize] public actionresult changepassword() { return view(); } [authorize] [httppost] public actionresult changepassword(string oldpassword, string newpassword) { bool changepasswordsucceeded; try { membershipuser currentuser = membership.getuser(user.identity.name, true /* userisonline */); changepasswordsucceeded = currentuser.changepassword(oldpassword, newpassword); } catch (exception) { changepasswordsucceeded = false; } if (changepasswordsucceeded) { return redirecttoaction("changepasswordsuccess"); } else { viewbag.validationmsg = "the old password incorrect."; viewbag.newpassword = newpassword; } // if got far, failed, redisplay form return view(); } [authorize] public actionresult changepasswordsuccess() { return view(); } } }
global.asax.cs
namespace myorg.myapp { public class mvcapplication : system.web.httpapplication { public static void registerglobalfilters(globalfiltercollection filters) { //filters.add(new handleerrorattribute()); filters.add(new infrastructure.handleexceptionsattribute()); // implementing custom exception handling } public static void registerroutes(routecollection routes) { routes.ignoreroute("{resource}.axd/{*pathinfo}"); routes.maproute( "default", // route name "{controller}/{action}/{id}", // url parameters new { controller = "home", action = "index", id = urlparameter.optional } // parameter defaults ); } protected void application_authenticaterequest(object sender, eventargs e) { httpcookie authcookie = request.cookies[formsauthentication.formscookiename]; if (authcookie != null) { formsauthenticationticket ticket = formsauthentication.decrypt(authcookie.value); string userid = ticket.name; customprincipal principal = new customprincipal(userid); httpcontext.current.user = principal; } } protected void application_postauthenticaterequest(object sender, eventargs e) { httpcookie authcookie = request.cookies[formsauthentication.formscookiename]; if (authcookie != null) { formsauthenticationticket authticket = formsauthentication.decrypt(authcookie.value); javascriptserializer serializer = new javascriptserializer(); customprincipalserializemodel serializemodel = serializer.deserialize<customprincipalserializemodel>(authticket.userdata); customprincipal newuser = new customprincipal(authticket.name); newuser.userid = serializemodel.userid; newuser.username = serializemodel.username; httpcontext.current.user = newuser; } } protected void application_start() { arearegistration.registerallareas(); registerglobalfilters(globalfilters.filters); registerroutes(routetable.routes); } } }
web.config
<?xml version="1.0"?> <configuration> <connectionstrings> <add name="***" connectionstring="***" /> </connectionstrings> <appsettings> <add key="webpages:version" value="1.0.0.0"/> <add key="clientvalidationenabled" value="true"/> <add key="unobtrusivejavascriptenabled" value="true"/> </appsettings> <system.web> <compilation debug="true" targetframework="4.0"> <assemblies> <add assembly="system.web.abstractions, version=4.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35" /> <add assembly="system.web.helpers, version=1.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35" /> <add assembly="system.web.routing, version=4.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35" /> <add assembly="system.web.mvc, version=3.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35" /> <add assembly="system.web.webpages, version=1.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35" /> </assemblies> </compilation> <authentication mode="forms"> <forms loginurl="~/account/logon" timeout="2880" /> </authentication> <machinekey validationkey="***" decryptionkey="***" validation="sha1" /> <membership defaultprovider="myappmembershipprovider" userisonlinetimewindow="15"> <providers> <clear /> <add name="myappmembershipprovider" type="myorg.myapp.infrastructure.myappmembershipprovider" connectionstringname="dummy" enablepasswordreset="true" requiresquestionandanswer="true" writeexceptionstoeventlog="true" /> </providers> </membership> <rolemanager enabled="false"> <providers> <clear/> <add name="aspnetsqlroleprovider" type="system.web.security.sqlroleprovider" connectionstringname="applicationservices" applicationname="/" /> <add name="aspnetwindowstokenroleprovider" type="system.web.security.windowstokenroleprovider" applicationname="/" /> </providers> </rolemanager> <pages> <namespaces> <add namespace="system.web.helpers" /> <add namespace="system.web.mvc" /> <add namespace="system.web.mvc.ajax" /> <add namespace="system.web.mvc.html" /> <add namespace="system.web.routing" /> <add namespace="system.web.webpages"/> </namespaces> </pages> </system.web> <system.webserver> <validation validateintegratedmodeconfiguration="false"/> <modules runallmanagedmodulesforallrequests="true"/> </system.webserver> <runtime> <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentassembly> <assemblyidentity name="system.web.mvc" publickeytoken="31bf3856ad364e35" /> <bindingredirect oldversion="1.0.0.0-2.0.0.0" newversion="3.0.0.0" /> </dependentassembly> </assemblybinding> </runtime> </configuration>
public override membershipuser createuser(string username, ...) { /* want switch on uses userid instead of username */ }
unfortunately, cannot modify membership provier methods' parameters.
here basic concept -
step 1
when user enters username , password @ login control, membership provide calls validateuser. create authentication ticket , save username in encrypted cookie.
step 2
when user requests sub sequence pages, membership provider retrieves username cookie, , calls getuser.
Comments
Post a Comment