Loginn
For å hjelpe brukeren dersom han glemmer passordet, får han tilbud om å spare tre verdier: fødselsår, postnummer og lykketall. Hva dette er, tekst eller tall, er det samme.
Passordene lagres i en enkel XML-struktur:
<?xml version="1.0" encoding="utf-8"?> <users> <user name="ole" pwd="olsen" tag1="46" tag2="1784" tag3="7" /> <user name="kari" pwd="karlsen07" tag1="23" tag2="2090" tag3="12" /> </users>
Alle de aktuelle dialogfragmentene er laget som Views innenfor en MultiView. Vi kan si at hvert View beskriver en tilstand i logginnsekvensen, og vi kan lage et tilstandsdiagram som planleggings- og dokumentsajonshjelpemiddel.
Webside
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Registrering</title> <link rel="Stylesheet" type="text/css" href="StyleSheet.css" /> <script language="javascript" type="text/javascript"> // <!CDATA[ function Button5_onclick() { document.getElementById('show_password').innerHTML= document.getElementById('hidden_password').innerHTML; return false; } // ]]> </script> </head> <body> <asp:Label ID="LabelHeader" runat="server" Text="Velkommen til dette vevstedet" CssClass="mainheader"></asp:Label> <form id="form1" runat="server"> <div> <asp:MultiView ID="MultiView1" runat="server"> <!-- ******************** introduction *********************** --> <asp:View ID="View1" runat="server"> <fieldset> <legend>Du må registrere deg</legend> <div> <br /> Jeg er allerede registrert:<br /> </div> <div> <br /> Navn: <input id="Text1" type="text" runat="server" style="width: 168px; height: 16px" /> <asp:Label ID="BadNameIntro" runat="server" CssClass="errormsg" Width="226px"> </asp:Label> </div> <div> <br /> Passord: <input id="Password1" type="password" runat="server" style="width: 167px" /> <asp:Label ID="BadPwdIntro" runat="server" CssClass="errormsg" Width="226px"> </asp:Label><br /> <br /> <input style="margin-left:200px" id="Button1" runat="server" type="button" value="Slipp meg inn" onserverclick="Button1_ServerClick" /><br /> </div> <br /> <hr /> <br /> <input id="Button2" type="button" runat="server" value="Jeg er ny, registrer meg" onserverclick="Button2_ServerClick" /> <br /> <br /> <input id="Button3" type="button" runat="server" value="Jeg har glemt passordet" onserverclick="Button3_ServerClick" /> </fieldset> </asp:View> <!-- ******************** handle new user ***************** --> <asp:View ID="View2" runat="server"> <fieldset> <legend>Registrering av ny bruker</legend> <br /> Navn: <input id="Text2" type="text" runat="server" style="width: 145px" /> <asp:Label ID="BadName" runat="server" CssClass="errormsg" Width="226px"></asp:Label><br /> Passord: <input id="Password2" style="width: 147px" type="password" runat="server" /> <asp:Label ID="BadPwd" runat="server" CssClass="errormsg" Width="229px"></asp:Label><br /> Gjenta passord: <input id="Password3" style="width: 148px" type="password" /><br /> <div class="msg">Hvis du fyller ut de 3 feltene nedenfor kan du få hjelp hvis du glemmer passordet</div> Fødselsår: <input id="Text3" style="width: 52px" type="text" runat="server"/><br /> Postnummer: <input id="Text4" style="width: 54px" type="text" runat="server" /><br /> Lykketall: <input id="Text5" style="width: 53px" type="text" runat="server"/><br /> <input id="Submit1" type="submit" value="Registrer meg" runat="server" onserverclick="Submit1_ServerClick"/><br /> </fieldset> </asp:View> <!-- *************** handle forgetfull user ********** --> <asp:View ID="View3" runat="server"> <fieldset> <legend>Hjelp for å komme inn</legend> <br /> Fødselsår: <input id="Text6" style="width: 52px" type="text" runat="server"/><br /> Postnummer: <input id="Text7" style="width: 54px" type="text" runat="server" /><br /> Lykketall: <input id="Text8" style="width: 53px" type="text" runat="server"/><br /> <input style="margin-left:200px" id="Submit2" type="submit" value="Finn meg" runat="server" onserverclick="Submit2_ServerClick"/> <br /> </fieldset> </asp:View> <!-- ************ You are inside ************* --> <asp:View ID="View4" runat="server"> <fieldset> <legend>Du er registrert og logget inn</legend> <br /> <asp:Label ID="SuccessName" runat="server" Text="Label"> </asp:Label><br /> <br /> <asp:Button ID="Button6" runat="server" Text="Logg ut" OnClick="Button6_Click" /></fieldset> </asp:View> <!-- ************* log in failed ************ --> <asp:View ID="View5" runat="server"> <fieldset> <legend>Beklager</legend> <br /> Finner deg ikke <asp:Label ID="userName" runat="server" Text="Label"></asp:Label><br /> <br /> <input id="Button4" type="button" runat="server" value="OK" onserverclick="Button4_ServerClick" /> </fieldset> </asp:View> <!-- *************** already exist *************** --> <asp:View ID="View6" runat="server"> <fieldset> <legend>Finnes allerede</legend> <br /> <span style="color: #0046d5"> En bruker med dette navnet finnes allerede:<br /> <br /> </span> <input id="Submit3" type="submit" value="Prøv igjen" runat="server" onserverclick="Submit3_ServerClick" /> <input id="Submit4" type="submit" value="Gir opp" runat="server" onserverclick="Submit4_ServerClick" /> <br /> </fieldset> <!-- ************ confirmed help ************* --> </asp:View> <asp:View ID="View7" runat="server"> <fieldset> <legend>Du er funnet</legend> <asp:label style="display:none" ID="hidden_password" runat="server"></asp:label> <asp:Label ID="username2" runat="server" Text="Label"> </asp:Label> Passordet ditt er: <span id="show_password"> <input id="Button5" type="button" value="Vis" onclick="return Button5_onclick()" /> </span> <br /><br /> <input id="Submit5" type="submit" runat="server" value="OK" onserverclick="Submit5_ServerClick" /> </fieldset> </asp:View> </asp:MultiView> </div> </form> </body> </html>
Programkode
Default.aspx.cs
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.IO; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) MultiView1.SetActiveView(View1); // reset all errormessages BadNameIntro.Text = ""; BadPwdIntro.Text = ""; BadName.Text = ""; BadPwd.Text = ""; // set filepath for passwordadmin pasadmin.setFileName( String.Format(@"{0}\App_Data\users.xml", Path.GetDirectoryName(Request.PhysicalPath))); // check cookies HttpCookie c=Request.Cookies["user"]; if(c!=null) { SuccessName.Text = c.Value; MultiView1.SetActiveView(View4); return; } } protected void setCookie(String name) { HttpCookie cook = new HttpCookie("user"); cook["Navn"] = name; Response.Cookies.Add(cook); } protected void killCookie() { HttpCookie cook = new HttpCookie("user"); cook.Expires = DateTime.Now.AddDays(-1d); Response.Cookies.Add(cook); } protected void Button1_ServerClick(object sender, EventArgs e) { // slipp meg inn String name = Text1.Value; String pwd = Password1.Value; // control if (name.Length == 0) { BadNameIntro.Text = "mangler navn"; return; } if (pwd.Length == 0) { BadPwdIntro.Text = "mangler passord"; return; } if (pasadmin.OldUserOk(name, pwd)) { // du er inne: SuccessName.Text = name; setCookie(SuccessName.Text); MultiView1.SetActiveView(View4); } else { // sorry MultiView1.SetActiveView(View5); } } protected void Button2_ServerClick(object sender, EventArgs e) { // new user, register me MultiView1.SetActiveView(View2); } protected void Button3_ServerClick(object sender, EventArgs e) { // forgotten the password, help him MultiView1.SetActiveView(View3); } protected void Button4_ServerClick(object sender, EventArgs e) { // user did not get inn and has received a message MultiView1.SetActiveView(View1); } protected void Submit1_ServerClick(object sender, EventArgs e) { // user submit application as new user String Name = Text2.Value; String Pwd1 = Password2.Value; String Pwd2 = Password2.Value; String Hlp1 = Text3.Value; String Hlp2 = Text4.Value; String Hlp3 = Text5.Value; // control if (Name.Length == 0) { BadName.Text = "mangler navn"; return; } if ((Pwd1.Length < 3) || (Pwd2.Length < 3) || (Pwd1.CompareTo(Pwd2) != 0)) { BadPwd.Text = "to identiske passord, lenger enn 3 tegn"; return; } // user exists already, we pretend name identity // but is really name and password identity if (pasadmin.OldUserOk(Name, Pwd1)) { // sorry already registered MultiView1.SetActiveView(View6); return; } String res = pasadmin.RegisterUser(Name, Pwd1, Hlp1, Hlp2, Hlp3); if (res != null) { SuccessName.Text = Name; setCookie(SuccessName.Text); MultiView1.SetActiveView(View4); } } protected void Submit2_ServerClick(object sender, EventArgs e) { // attempt to localize user based on the three fields String Hlp1 = Text6.Value; String Hlp2 = Text7.Value; String Hlp3 = Text8.Value; String[]NP = pasadmin.FindUser(Hlp1, Hlp2, Hlp3); if (NP == null) { userName.Text="?"; MultiView1.SetActiveView(View5); return; } // found him, ok let him in String Pwd = NP[0]; String Name = NP[1]; hidden_password.Text = Pwd; username2.Text = Name; MultiView1.SetActiveView(View7); } protected void Submit3_ServerClick(object sender, EventArgs e) { // try again after having submitted existing data MultiView1.SetActiveView(View2); } protected void Submit4_ServerClick(object sender, EventArgs e) { // give up after having submitted existing data MultiView1.SetActiveView(View1); } protected void Submit5_ServerClick(object sender, EventArgs e) { // user is told he is found, and shown the password // let him in SuccessName.Text = username2.Text; setCookie(SuccessName.Text); MultiView1.SetActiveView(View4); } protected void Button6_Click(object sender, EventArgs e) { // want to log out killCookie(); MultiView1.SetActiveView(View1); } }
pasadmin.cs
Administrasjon av passordfila er lagt til en egen klasse, pasadmin. Denne kan lett byttes ut. Klassen har følgende rutiner som brukes utenfra, fra Dafault.aspx.cs: RegisterUser, FindUser, OldUserOk, setFileName.
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Xml; using System.IO; /// <summary> /// Summary description for pasadmin /// </summary> public class pasadmin { static String FileName; public pasadmin(String filename) { } public static void setFileName(String fn) { // set filename from usercode, since usercode knows the path ? FileName=fn; } static String GetXmlFileName() { return FileName; } static XmlDocument GetUserDoc() { XmlDocument doc = new XmlDocument(); try { String FileName = GetXmlFileName(); doc.Load(FileName); return doc; } catch (Exception ex) { // errormessage return null; } } static void SetUserDoc(XmlDocument doc) { try { String FileName = GetXmlFileName(); FileStream fs = new FileStream(FileName, FileMode.Open); XmlTextWriter writer = new XmlTextWriter(fs, System.Text.Encoding.UTF8); writer.Formatting = Formatting.Indented; doc.WriteContentTo(writer); writer.Flush(); writer.Close(); } catch (Exception ex) { // errormessage } } static public bool OldUserOk(String name, String passwd) { XmlDocument doc = GetUserDoc(); if (doc == null) return false; XmlNodeList users = doc.GetElementsByTagName("user"); foreach (XmlElement user in users) { String name_att = user.GetAttribute("name"); String pwd_att = user.GetAttribute("pwd"); if ((name_att.CompareTo(name.Trim()) == 0) && (pwd_att.CompareTo(passwd.Trim()) == 0)) return true; } return false; } static public String[] FindUser(String Hlp1, String Hlp2, String Hlp3) { XmlDocument doc = GetUserDoc(); if (doc == null) return null; XmlNodeList users = doc.GetElementsByTagName("user"); foreach (XmlElement user in users) { String t1 = user.GetAttribute("tag1"); String t2 = user.GetAttribute("tag2"); String t3 = user.GetAttribute("tag3"); if ((t1.CompareTo(Hlp1.Trim()) == 0) && (t2.CompareTo(Hlp2.Trim()) == 0) && (t3.CompareTo(Hlp3.Trim()) == 0)) { String[] L = new String[2]; L[0] = user.GetAttribute("pwd"); L[1] = user.GetAttribute("name"); return L; } } return null; } static public String RegisterUser(String Name, String Pwd, String Hlp1, String Hlp2, String Hlp3) { // set nonempty values if (Hlp1.Length == 0) Hlp1 = "_no_value_at_all"; if (Hlp2.Length == 0) Hlp2 = "_no_value_whatsoever"; if (Hlp3.Length == 0) Hlp3 = "_no_value_here"; XmlDocument doc = GetUserDoc(); if (doc == null) return null; XmlElement new_user = doc.CreateElement("user"); new_user.SetAttribute("name", Name.Trim()); new_user.SetAttribute("pwd", Pwd.Trim()); new_user.SetAttribute("tag1", Hlp1.Trim()); new_user.SetAttribute("tag2", Hlp2.Trim()); new_user.SetAttribute("tag3", Hlp3.Trim()); doc.DocumentElement.AppendChild(new_user); SetUserDoc(doc); return "ok"; } }
Cookies
Løsnongen setter en cookie når brukeren er godkjent og fjerner den samme cookien når brukeren logger ut. Koden for å sette cookie er slik, fra Default.aspx.cs:
protected void setCookie(String name) { HttpCookie cook = new HttpCookie("user"); cook["Navn"] = name; Response.Cookies.Add(cook); }
Koden for å fjerne samme cookie er slik, også fra Default.aspx.cs:
protected void killCookie() { HttpCookie cook = new HttpCookie("user"); cook.Expires = DateTime.Now.AddDays(-1d); Response.Cookies.Add(cook); }
Inputkontroll
Løsningen har en rudimentær inputkontroll på tjeneren. Det vil være en klar forbedring å legge en bedre inputkontroll på klientsiden.