home · blog · groups · about us · contact us
DevelopmentNow Blog
 Wednesday, March 01, 2006
 
 

ASP.NET 2.0's new membership provider allows for three different ways to protect user's passwords via the passwordFormat attribute:

  • Clear: passwords are stored in clear text. Fine for non-sensitive applications.
  • Encrypted: passwords are encrypted. Note that you will have to put a hard-coded decryption key in the <machineKey> tag in your web.config or machine.config. Otherwise you'll get a "You must specify a non-autogenerated machine key to store passwords in the encrypted format" error when trying to create users. To create a machineKey tag with a set of random tags, you can use my machineKey generator (source code included).
  • Hashed: passwords are not stored in the database at all, only an SHA-1 hash. This means passwords can not be retrieved at all -- if a user forgets their password, they'll have to request a new, randomly-generated one.

Below is an example of a <membership> tag using the Encrypted password format.

        <membership defaultProvider="MySqlMembershipProvider" >
            <providers>
                <add name="MySqlMembershipProvider"
                connectionStringName="MyLocalSQLServer"
                applicationName="MyAppName"
                                 requiresUniqueEmail="false" enablePasswordRetrieval="true"
                                 enablePasswordReset="true" requiresQuestionAndAnswer="false"
                                 passwordFormat="Encrypted"
                                 minRequiredPasswordLength="4"
                                 minRequiredNonalphanumericCharacters="0"
                type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            </providers>
        </membership>

March 1, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 
 

I made some updates to the machineKey generation program I mentioned in my machineKey generation post. It now returns a complete machineKey tag for ASP.NET 1.1 or 2.0 that you can copy and paste into your web.config or machine.config. You can run the generator or download the code here.

March 1, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Thursday, February 16, 2006
 
 
Robert Scoble, blogger-under-notice from Microsoft, posted an interesting blurb about search ranking and secret blogger cliques. He suggested sticking the word brrreeeport in your blog to prove his point about tagging on Technorati.
February 16, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Wednesday, February 15, 2006
 
 

I was struggling for a while with how to get a profile of the queries being sent to MySQL. All my searches suggested running the debug version of MySQL, but it would either log WAY WAY too much information, or else not log the queries at all. I wanted something akin to the SQL Server Profiler, so I could just see the SQL and proc calls. Is that so much to ask? 

I eventually found the solution in the NHibernate forums (of all places), and it doesn't require running the debug version of MySQL at all. Inside your MySQL option file (e.g. "C:\Program Files\MySQL\MySQL Server 5.0\my.ini" or some other location), add the following line inside the [mysqld] section:

log="C:/Program Files/MySQL/MySQL Server 5.0/mysql.log"

Restart the MySQL service, and you'll get a nice log file continuously updated with all queries being sent to MySQL. You can view it with TextPad or some other text editor that can auto-refresh files when they change.

 

February 15, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 
 

If you're getting the above error when loading your Visual Studio project, you should first ensure that the web server on your PC is running. Then confirm that .NET is installed by running "aspnet_regiis -i" in your windows\microsoft.net\framework\v1.1.4322 folder. Then open up Control Panel->Administrative Tools->Internet Information Services, and ensure the web site is running.

If you try to start the "Default Web Site" on your PC and get a strange error, make sure you don't have Skype running. It listens on port 80, preventing IIS from doing so. Which prevents your web projects from running in Visual Studio. :)

February 15, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 
 

Like many developers, I've been intrigued by the hype around Ruby on Rails, but of course I don't have a Linux box handy and don't feel like setting up Apache, etc to try it out. What's a lazy programmer to do?

Enter Instant Rails, especially designed for Windows developers. From the description:

Instant Rails is a one-stop Rails runtime solution containing Ruby, Rails, Apache, and MySQL, all preconfigured and ready to run. No installer, you simply drop it into the directory of your choice and run it. It does not modify your system environment.

You can download Instant Rails here.

 

February 15, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Tuesday, February 14, 2006
 
 

On one of my projects, the client noted getting occasional errors when filling out forms. The errors were something like "Unable to validate data" or HttpException: Invalid_Viewstate. After some research, it turns out the error is due to the viewstate MAC (message authentication code) changing between postbacks, or more specifically, the viewstate MAC in the page is different than the MAC the server is expecting.

What is the ViewState MAC?

MAc stands for Message Authentication Code -- it's a way to ensure that messages haven't been tampered with.

As you know, the ViewState is ASP.NET's way of persisting form data across postbacks (John Peterson has a good overview if you want to know basic ViewState facts). This data appears in base-64 encoded form inside a hidden form value called __VIEWSTATE. The MAC is an additional value designed to prevent changing or tampering with viewstate data. ASP.NET looks at the data in the viewstate and, using a secret validation key, generates a hash from that data using SHA-1. That hash value is the MAC, and ASP.NET includes it in the form. When a postback occurs, your browser passes the form data, the viewstate, and the MAC value to the web server. ASP.NET looks at the submitted viewstate data and generates another MAC value on the fly. It then compares that MAC value to the MAC value contained in the POST information. If the two values match, then no one has tampered with the viewstate. If the newly-generated MAC doesn't match what comes across, however, then ASP.NET believes someone has monkeyed with the data in the viewstate and throws an Invalid_Viewstate error.

Why would the MAC be different from what the server expected?

Several things can cause the MAC to not match what ASP.NET is expecting:

  • Some hacker (maybe even you?) actually tried to change the data in the viewstate
  • The form data got cut off during submission to the server (due to timeout, crappy proxy server, etc)
  • Using Server.Transfer can cause it to happen
  • The validation key used to generate the previous MAC is different than the key being used to generate the new MAC

The last issue can happen more easily that you'd expect. One way is if you're running a web farm. By default, the validation key used to create the MAC is randomly generated by ASP.NET when the application pool starts up. This ensures that the validation key is unique and changes periodically. However, since the key is different from server to server, if you're viewing a page on Server A and post it to Server B, when Server B generates a MAC based on the viewstate data, that value won't match the MAC value when the page was initially served by Server A. Thus, you'll get an Invalid_Viewstate error.

Another reason the validation key (and thus the MAC) will be different is if you cross application pools. If you view a page running in pool A, and post to another page on pool B (e.g. through Server.Transfer), the key will be different & you'll get a mismatch.

Lastly, the validation  key can change mid-session for users if the application pool restarts. Assume some user is viewing a page on your site and filling out a form. While they're doing that, some sysadmin restarts the pool, thus generating a new key. When the user posts the page they'll get an Invalid_Viewstate error. The application can also restart if it is set to shut down while idle (the default is to shut down pools that have been idle for 20 minutes). Imagine a user who views a page on your site, goes away for 10 minutes then maybe spends 20 minutes filling in the form on the page. Meanwhile, no one else is on your site, so the application pool times out & shuts down. When the user finally posts the form (30 minutes after viewing it), the application pool will start back up, create a new validation key, generate a new MAC, notice that the MAC values don't match, and reward you user's diligence with an Invalid_Viewstate error.

Avoiding MAC Mismatch

There are a few ways to avoid MAC mismatch mishaps:

  1. Don't use the ViewState if you don't need to. Not only will it avoid the whole MAC issue, but your pages will run faster to boot.
  2. Turn off MAC generation by setting enableViewStateMac=false in the page or web.config. This isn't recommended, since the MAC helps prevent people from tampering with your viewstate data. But if tampering with viewstate data isn't a concern (and it may not be for some applications where there's no risk of fraud or security breaches), you can turn it off.
  3. Prevent your application pool from restarting by disabling the auto recycle and idle timeout settings in the application pool. This isn't a 100% guarantee that the pool won't restart, but it does help.
  4. Hard-code the MAC validation key so that it's always the same. I recommend this approach for web farms and/or if your application pool keep restarting for whatever reason (overzealous admins, memory leaks, etc). The biggest risk is now your key is hard-coded in a file, so you need to make sure your server is secure so that people don't get that key (otherwise they could hack your viewstate). You can hardcode the key in the <machineKey> tag in the machine.config or web.config, like this:
    <machineKey  
    validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7"           
    decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
    validation="SHA1"
    />

    If you're using ASP.NET 2.0, your machineKey tag should also have the decryption attribute, like this:
    <machineKey  
    validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7"           
    decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
    validation="SHA1"
    decryption="AES"
    />

    Note, the above values are just examples! Generate your own values for validationKey and decryptionKey (and keep them secret) using the code from this MSDN page. A modified version is shown below:

    using System;
    using System.Text;
    using System.Diagnostics;
    using System.Security;
    using System.Security.Cryptography;
    
    class App {
    		static void Main(string[] args)
    		{
    			Debug.WriteLine("64-byte validationKey: " + getRandomKey(64));
    			Debug.WriteLine("24-byte decryptionKey: " + getRandomKey(24));
    		}
    
    		public static string getRandomKey(int bytelength)
    		{
    			int len = bytelength * 2;
    			byte[] buff = new byte[len/2];
    			RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    			rng.GetBytes(buff);
    			StringBuilder sb = new StringBuilder(len);
    			for (int i=0; i<buff.Length; i++)
    				sb.Append(string.Format("{0:X2}", buff[i]));
    			return sb.ToString();
    		}
    }
    

Hopefully the above will help you out if you encounter strange "invalid viewstate" errors, or if you plan to use the viewstate in a web farm, or if you just like knowing more about the viewstate.

P.S. While typing this entry, I accidentally hit the thumb button on my MX510, which by default hits the browser's "Back" button. Which sent me back to the previous page, which made me lose everything I had typed. Which was a super downer. So, disable that mouse button if you don't use it, or you'll be sorry! :)

February 14, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Sunday, February 05, 2006
 
 

I was using Kayak today and noticed they had a link about their technology. One thing I noticed was that they use Ruby, which I've been reading about more lately, especially the uber-sexy Ruby on Rails. But Kayak also mentioned that they use memcached to cache common database results. It's basically a super-fast distributed dictionary (key/value pairs) object that you can spread across multiple servers without replicating data all over the place.

Since I'm a Microsoft developer, I normally cache web server stuff using the good ol' Cache object, or maybe the Caching Enterprise Library. Which works fine. But memcached makes a good point, in that if you have, say, 50 web servers, running multiple processes, then you're going to be potentially storing the same data multiple times on every machine. memcached stores your data once, and scales across as many machines as you run it on. And since memcached is built as a caching system, it could potentially be much faster than caching things in a database.

But don't take my word for it, especially since I'm just paraphrasing their "about" page. Read more about how it works on the memcached home page ... if it sounds intriguing to you, you should check it out. What's the worst that could happen? :)

February 5, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Tuesday, January 31, 2006
 
 

I'm in Portland, but I'm working on some projects with people in Chicago. In order to collaborate better, I was looking into ways to share my desktop with other users. I've used WebEx and other tools before, but I wanted something free. I also wanted something that worked through NATs (since I'm behind one), supported my multiple monitors, and was very easy for non-technical people to use. As in "click-on-this-URL-and-see-my-desktop" easy. So I started surfing around and saw the suggestion to use VNC, which I'd used in the past but not recently. 

VNC (Virtual Network Computing) is a desktop sharing/remote control program like Remote Desktop, PC Anywhere, etc. There is a server part (VNC Server) that runs on the shared PC, and a viewer (VNC Viewer) application that is run by people wanting to view and/or control the shared PC. The original VNC was open source, which spawn variants like TightVNC, UltraVNC, RealVNC's Free Edition, and others. RealVNC is the group that originally created VNC, and they have a limited, free version, along with some better non-free ($30-$50) versions.

Web-based Desktop Sharing

Users normally connect to shared desktops using the Standalone VNC Viewer, an installed application that connects over port 5900. However, VNC (at least RealVNC and UltraVNC) also offers a web-based java viewer. So instead of installing software, user could instead open a web browser, go to a URL, and connect to a shared desktop via a java applet. Easy peasy.

Behind the scenes, the VNC Server contains a mini web service that listens on port 5800. A user can open a web browser and connect to the IP of a shared computer, e.g. http://somesharedpc.yourdomain.com:5800. When users hit that page, they see a web page and a small java applet that allows them to connect to that PC's VNC server (if running). Once connected, they can see the desktop, use the mouse and keyboard, transfer files, and share the clipboard. 

I was able to connect to my PC from other computers on my LAN, but I wanted to make sure that my partners in Chicago could also see my desktop. Since my computer is behind a firewall, I needed to connect to my router and forward ports 5800 (for the web-based sharing) and 5900 (if people use the standalone viewer). Once that was done, VNC worked just fine over the internet.

Note that you can configure the VNC Server to prompt you before allowing connections, and to only offer view-only access to users.

Remote Support

UltraVNC also offers an intriguing remote support application called SingleClick. It's a small EXE that users can download in order to let you view and control their desktops.

SingleClick Screenshot

As a software developer, you can brand and customize the EXE with your own logo, text, IP address, button labels, etc. You can also include your own rc4 encryption key for secure connections. Once you have your customized SingleClick EXE, you can put it on your web site, email it to clients, etc. Then when a client (or technophobic relative) has computer troubles, you run the VNC Viewer, the user runs the SingleClick EXE and authorizes the connection, and after a few seconds you're logged into their computer. Once the session is done, SingleClick uninstalls itself from the user's PC. And although you (as the viewer) need to ensure port 5500 is forwarded to your PC, your users normally won't need to worry about firewall settings unless their firewall is blocking port 5500 outbound (which would only be the case in secure corporate environments). If that's the case you could always reconfigure your SingleClick EXE to run over port 80, which should be allowed in almost any company.

There is a pretty detailed walkthrough in the UltraVNC forums on creating your own SingleClick EXE to perform remote support. I made my own EXE and was pleased with how easily it worked. I do wish it was a bit prettier, though. Since it's open source, you might be able to make your own skin.

Other Features

Some other interesting features I noticed were

  • file transfer (TightVNC and UltraVNC)
  • multi-monitor support (UltraVNC and RealVNC)
  • Microsoft Windows Logon authentication, so users have to use MS logins to connect (UltraVNC and RealVNC)
  • a special video driver to speed up connections and reduce CPU utilization on the server (UltraVNC)
  • chat windows (UltraVNC)
  • some cool networking options like Repeater and NAT-to-NAT to get around NAT issues (UltraVNC)

Security

While the password exchange is secured in VNC, any text typed during the sharing session is normally passed in plaintext. That's probably OK if you're not typing anything sensitive, but any passwords, credit cards, etc. would be out in the open. In order to secure the entire session, you can install an SSH server and use SSH tunneling to connect to the shared computer. Non-Windows users can use OpenSSH while Windows users can use SSHWindows and follow Digital Media Minute's SFTP install guide to get SSH running (SFTP uses SSH).

If you don't want to deal with SSH, RealVNC's non-free versions support session encryption, and UltraVNC supports a Data Stream Encryption plugin.

Conclusion

When I used VNC years ago, it worked well but was pretty basic. But now I'm pleasantly surprised at the new features, speed, and stability. RealVNC's paid versions might be nice if you need tech support, want easy-to-use session encryption, and like paying for software. If you're a novice user or just want the no-frills version, you could also try RealVNC's free version -- I found the setup & installation of RealVNC to be a bit easier than UltraVNC. Otherwise I'd suggest giving UltraVNC a whirl.

If you're mostly interested in the remote support features, but want something easier to use and don't mind paying for it, there are some non-free applications that are based on VNC. EchoWinVNC is one, as is NetworkStreaming.

January 31, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Wednesday, January 25, 2006
 
 

The best way to get cheap, dedicated employees is to get them when they're young (before they know any better), have them work on projects they think are cool, and give them lots of free candy and soda. The more sugar the better. 

But why mess around with newly-minted Comp Sci college grads? That's so 2005. I instead suggest finding kids between 10 and 14 and having them learn the Kid's Programming Language. It's based on .NET, but with a simplified IDE and API.

Put your kids (or spouse, or neighbor, or relative) to work building a next-generation tool so that you can retire young and finally have time to enjoy World of Warcraft. :)

Note: I am being tongue-in-cheek about "cheap labor." I don't advocate child labor or anything. I just thought this tool was cool (especially considering the brain drain & dropping numbers of IT grads) ad might be a good way to bond with youngins or help your local middle school students get into IT. But...I couldn't resist being flippant.

 

January 25, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 
 

Fresh from reddit: Joe Hewitt (the DOM inspector dude) has recently released FireBug, a Firefox plugin that's "like a combination of the Javascript Console, DOM Inspector, and a command line Javascript interpreter." It looks perty sweet.

FireBug Screenshot

Grab it in the Mozilla Addons site.

January 25, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]