protected void processLogin() { HttpCookie authcookie = Request.Cookies[FormsAuthentication.FormsCookieName]; if (authcookie != null) { FormsAuthenticationTicket tryTicket = (FormsAuthenticationTicket)FormsAuthentication.Decrypt(authcookie.Value); if (User.Identity.IsAuthenticated) { string userid = User.Identity.Name; Response.Cookies.Remove(FormsAuthentication.FormsCookieName); } } InValid.Text = null; Page.Validate(); allClients = (List<ClientInformation>)ViewState["allClients"]; knownAddresses = (List<string>)ViewState["knownAddresses"]; names = (List<string>)ViewState["names"]; clientDefinitions = (List<string>)ViewState["clientDefinitions"]; bindings = (List<BindingInformation>)ViewState["bindings"]; ClientInformation client = null; BindingInformation binding = bindings.Find(delegate(BindingInformation bindingItem) { client = allClients.Find(delegate(ClientInformation clientExist) { return clientExist.ElementName.Equals(clients.SelectedValue); }); return bindingItem.BindingConfigurationName.Equals(client.BindingConfiguration); }); if (Page.IsValid) { //Notes on security: //We are using ASP.NET Forms authentication from ConfigWeb, which automates the authentication process against //either a simple list of valid users, or a backend database of registered users (ConfigWeb uses this mechanism), //Windows Active Directory, or any pluggable mechanism based on the extensibility of Forms Authentication in ASP.NET 2.0. //Via Forms Authentication, ASP.NET provides automatic authentication for restricted pages, and automates redirects to login forms //such as this one. In addition, security can be set with WCF bindings, which support transport, message, and transport with //message credentials. You can add additional WCF binding configurations and client configurations to ConfigWeb web.config, and they will //automatically show up as drop-down options on the login page. The Configuration Service itself authenticates every //request against its registered users database; with service operations restricted based on the user rights for that registered user. //The remote Configuration Service you are logging into must support the binding option you choose (via the selected Client Configuration) on login; with WCF //a service host can simultaneously support many different bindings (perhaps with different security settings), many different //listen endpoints (URIs). And, clients can also support these different binding options, as illustrated with this login //page that allows netTcp (binary encoding); or basicHttp (SOAP/text-XML encoding) to be chosen as an option for login and //all subsequent requests for Configuration Service operations. Again, you could add different bindings to your Configuration //Service host, and simply add the appropriate client bindings (can generate via svcutil) to ConfigWeb web.config to //restrict access based on transport and/or message level security set in your binding configurations on client and host-- //for example, adding wsHttp support over https. See: // // http://msdn2.microsoft.com/en-us/library/ms735093.aspx // // //Finally, ASP.NET Forms authentication defaults to use SHA1 for HMAC Generation and AES for //Encryption, which is recommended. An application such as this in production on the public Internet //(vs. internal private net) would be run over SSL. An excellent security Patterns and Practices resource //on how to secure Internet applications can be found at: /// // http://msdn2.microsoft.com/en-us/library/aa302415.aspx // //Information on Forms Authentication, encryption and using Forms Authentication with SSL is available at: // // http://msdn2.microsoft.com/en-us/library/ms998310.aspx string userID = uid.Text; string password = pwd.Text; password = Input.LoginValidate(password, Input.EXPRESSION_PWORD); userID = Input.LoginValidate(userID, Input.EXPRESSION_USERID); if (userID==null || password == null) { InValid.Text = "Please enter a valid userid and/or password!"; return; } string address = null; if (!CheckBoxAddress.Checked) address = textboxaddress.Text.ToLower().Trim(); else address = ServiceAddress.Text.ToLower().Trim(); if (address == null || address == "") { InValid.Text = "Please enter a valid address!"; return; } Uri theUri = null; try { theUri = new Uri(address); } catch (Exception) { InValid.Text = "Please enter a valid address!"; return; } bool remap = false; ServiceConfigurationClient configProxy = null; ServiceUsers user = new ServiceUsers(0, userID, password, ConfigUtility.CONFIG_NO_RIGHTS, true, 0); try { user.UserId.Trim(); if (!CheckBoxAddress.Checked) { if (binding.BindingType != null) { switch (binding.BindingType) { case ConfigUtility.BASIC_HTTP_BINDING: { if (!client.ElementName.ToLower().Contains("t_security")) { if (!address.ToLower().StartsWith("https") && address.ToLower().StartsWith("http")) { break; } else if (address.ToLower().StartsWith("https")) { address = address.Remove(4, 1); textboxaddress.Text = address; theUri = new Uri(address); remap = true; break; } else { InValid.Text = "You have selected an <b>Http</b> configuration: Please enter a valid <strong>http</strong> address."; return; } } else { if (!address.ToLower().StartsWith("https") && address.ToLower().StartsWith("http")) { address = address.Insert(4, "s"); theUri = new Uri(address); textboxaddress.Text = address; remap = true; break; } else if (!address.ToLower().StartsWith("https")) { InValid.Text = "You have selected an <b>Https</b> configuration: Please enter a valid <strong>https</strong> address."; return; } break; } } case ConfigUtility.WS_HTTP_BINDING: { goto case ConfigUtility.BASIC_HTTP_BINDING; } case ConfigUtility.WS_2007_HTTP_BINDING: { goto case ConfigUtility.BASIC_HTTP_BINDING; } case ConfigUtility.NET_TCP_BINDING: { if (!address.ToLower().StartsWith("net.tcp")) { InValid.Text = "You have selected a <b>Tcp</b> configuration: Please enter a valid tcp address in form of net.tcp://"; return; } break; } } } } string theClientConfig = null; ServiceUsers returnUser=null; if (CheckBoxAddress.Checked) theClientConfig = ClientConfiguration.Text; else theClientConfig = clients.SelectedValue; configProxy = new ServiceConfigurationClient(theClientConfig, address, user); //Ok, request a login from the remote service LoginInfo returnInfo = configProxy.login(user); if (returnInfo!=null) returnUser = returnInfo.CsUser; //By default, the service will reject admin ops on a per request basis, but we will also reject login here //in ConfigWeb for non-admins. if (returnUser != null && returnUser.Rights >= ConfigUtility.CONFIG_DEMO_ADMIN_RIGHTS) { //OK--we are logged in! To allow scale out of ConfigWeb itself, we are going to jam some basic information into a cookie //as client-side session state. In secure scenarios, like on Azure, ConfigWeb is always run over https. This is an alternative //to distributed caching of session state, but only appropriate when the state per session is very, very small (a few strings below). string sessionInfo = address + (char)182 + returnUser.LocalUser.ToString() + (char)182 + returnUser.Password + (char)182 + returnUser.Rights.ToString() + (char)182 + returnUser.UserId + (char)182 + returnUser.UserKey.ToString() + (char)182 + theClientConfig + (char)182 + returnInfo.HostNameIdentifier + (char)182 + returnInfo.ConfigServiceName + (char)182 + returnInfo.ServiceHoster + (char)182 + returnInfo.ServiceVersion + (char)182 + returnInfo.RuntimePlatform + (char)182 + returnInfo.HostedServiceID; //FormsAuthentication.SetAuthCookie(returnUser.UserId, false); FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(3, returnUser.UserId,DateTime.Now, DateTime.Now.AddMinutes(ConfigSettings.CONFIGWEB_FORMSAUTH_TIMEOUT_MINUTES),false, sessionInfo); string hash = FormsAuthentication.Encrypt(ticket); HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash); Response.Cookies.Add(cookie); Response.Redirect(FormsAuthentication.DefaultUrl, true); } else { InValid.Text = ConfigSettings.EXCEPTION_MESSAGE_INVALID_LOGIN; } } catch (Exception e) { if (remap) InValid.Text = "<b>You entered an https or http address that did not match the selected client configuration binding, and the address was remapped to/from https to/from http automatically before attempting login. </b><br/><br/>"; else InValid.Text = ""; //Note if a service is misconfigured and will not start, the exception will likely be a web page; which has to be handled differently since its encoding is not text/xml, its text/html //with lots of characters that will not display if simply printed out on a label control. string displayMessage=null; string innerMessage = ""; if (e.Message.ToLower().Contains("<html>")) displayMessage = ConfigUtility.reMapExceptionForDisplay(e.Message); else displayMessage = e.Message; if (e.InnerException != null) innerMessage = "<br/>Inner Exception is: " + e.InnerException.Message; InValid.Text = InValid.Text + "Error Logging In. Exception is: <br/>" + displayMessage + innerMessage; } } }