<?xml version="1.0" encoding="UTF-8"?>
<article-node>
  <account-id type="integer">2</account-id>
  <author>Michael Slater</author>
  <aux>If your web application manages any private information, you should be using &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; (https://) for pages where that information is entered or displayed. Fortunately, implementing &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; isn&amp;#8217;t too hard, once you know what you need to do.</aux>
  <body>&lt;p&gt;If your web application manages any private information, you should be using &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; (https://) for those parts of the application. Any data sent over a plain http connection can be &amp;#8220;sniffed&amp;#8221; by any &lt;span class=&quot;caps&quot;&gt;ISP&lt;/span&gt; along the route that the packets take if you aren&amp;#8217;t using &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Fortunately, implementing &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; isn&amp;#8217;t too hard, once you know what you need to do. This article will talk you through the process. These are the steps we&amp;#8217;ll go through:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Create your private key&lt;/li&gt;
	&lt;li&gt;Create your certificate signing request&lt;/li&gt;
	&lt;li&gt;Get your certificate&lt;/li&gt;
	&lt;li&gt;Configure your web server&lt;/li&gt;
	&lt;li&gt;Set up your Rails application&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Creating your private key&lt;/h2&gt;
&lt;p&gt;The first thing you need is a private key, with which your certificate will be encrypted, and which will be used to encrypt your &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; pages before they are sent. You make the private key yourself. Assuming your server has openSSL installed, enter the following command in an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; shell:&lt;/p&gt;
&lt;pre&gt;
openssl genrsa -out domainname.key 1024
&lt;/pre&gt;
&lt;p&gt;This creates your private key in the file domainname.key (you should substitute your domain name for domainname, of course, although the name doesn&amp;#8217;t really matter). This key is unprotected, so you should ensure that this file is readable only by the root user:&lt;/p&gt;
&lt;pre&gt;
chmod 600 domainname.key
&lt;/pre&gt;
&lt;p&gt;Alternatively, you can create your key in an encrypted form that will require you to specify a passphrase when creating the key, and to enter that passphrase to access the key:&lt;/p&gt;
&lt;pre&gt;
openssl genrsa -des3 -out domainname.key 1024
&lt;/pre&gt;
&lt;p&gt;This makes your key more secure, but it has a big downside: once you&amp;#8217;ve installed the key, you&amp;#8217;ll need to enter the passphrase any time the web server is rebooted. If you&amp;#8217;re not around and there&amp;#8217;s an emergency reboot of your server, your site will be down until someone can log in and enter the key.&lt;/p&gt;
&lt;p&gt;If you do encrypt your key, don&amp;#8217;t forget your passphrase! Without it, your key, and the certificate that uses it, will be worthless, and there&amp;#8217;s no way to recover it.&lt;/p&gt;
&lt;h2&gt;Creating your certificate signing request&lt;/h2&gt;
&lt;p&gt;Now that you have your private key, you can create the certificate signing request (&lt;span class=&quot;caps&quot;&gt;CSR&lt;/span&gt;), which you&amp;#8217;ll need to get your certificate.&lt;/p&gt;
&lt;p&gt;In the &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; shell on your server, create your &lt;span class=&quot;caps&quot;&gt;CSR&lt;/span&gt; as follows:&lt;/p&gt;
&lt;pre&gt;
openssl req -new -key domainname.key -out domainname.csr
&lt;/pre&gt;
&lt;p&gt;You&amp;#8217;ll be prompted to provide the name of the company, the country, city, and state, and some other information. The most critical piece of information here is the common name, which must exactly match the domain of the server on which the certificate will be used, including any subdomain. Note that www counts as a subdomain, so one certificate works either with www.domainname.com &lt;strong&gt;or&lt;/strong&gt; with domainname.com. You can also buy a &amp;#8220;wildcard&amp;#8221; certificate, which works with any subdomain, but they&amp;#8217;re much more expensive (at this writing, $199 vs. $19.99 at GoDaddy). (To make your site work with or without the www prefix, you should be redirecting accesses to one or the other, so you&amp;#8217;ll only need a certificate for one of them.)&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t enter any of the &amp;#8220;extra&amp;#8221; information that you&amp;#8217;ll be prompted for. In particular, don&amp;#8217;t enter a challenge phrase, or the certificate signing authority won&amp;#8217;t be able to read your request.&lt;/p&gt;
&lt;p&gt;The file domainname.csr will now contain a string of text, which you&amp;#8217;ll shortly be providing to your certificate authority. The file contents should look something like this:&lt;/p&gt;
&lt;pre&gt;
-----BEGIN CERTIFICATE REQUEST-----
MIIBxjCCAS8CAQAwgYUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTETMBEGA1UE
BxMKU2ViYXN0b3BvbDEXMBUGA1UEChMOTXkgV2ViIENvbXBhbnkxGzAZBgNVBAMT
End3dy5kb21haW5uYW1lLmNvbTEeMBwGCSqGSIb3DQEJARYPbWVAbXlkb21haW4u
Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpyw/LtDRQo/MCtDlckqLz
Cghnod7OFjcGXqprRW15Vn8bTB4v2L29lx2n+U1uK9jWCO/bZFUzVDZ/ESWhCRN8
roqbNuCxBdAzpX2M92RPcZWPeK+cRaJ7kafn5B8kyTXHenYWBAu/epy1NG7fagoO
qV4nqmCv0EwTkeWm9uShjQIDAQABoAAwDQYJKoZIhvcNAQEEBQADgYEAgXpQ6E0/
SyX7r25VI1EoLz2lRBX6tkqhOoBlVAPzDVN88todMaLQlbCz0VXKP9eS78cZe8kJ
7jI+Ujmio7GQ8zFLwpMCXzGCkpri30wO4hsK1lfvC/ScPTEayISECUNlTlRbRztW
W7AH4Z67d47E1hctoitbXSCbQVOfGavm1mA=
-----END CERTIFICATE REQUEST-----
&lt;/pre&gt;
&lt;h2&gt;Getting your certificate&lt;/h2&gt;
&lt;p&gt;Now you need to choose where to get your certificate, and what level of verification to pay for. To understand the choices, keep in mind that an &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; certificate provides two separate functions:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It certifies, to varying degrees, the identity of the person or business that controls the web site.&lt;/li&gt;
	&lt;li&gt;It provides the public and private keys for encrypting communications with the site.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can get certificates at prices ranging from less than $20 to more than $1500, and they all provide the same encryption. The only difference is the degree to which they verify that you are who you say you are, and the seal that they give you to display on your web site. For more on certificates and certificate authorities, see &lt;a href=&quot;http://www.mslater.com/2007/5/9/implementing-ssl&quot;&gt;Implementing &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;&lt;/a&gt;. Or, if you don&amp;#8217;t care about all the fancy stuff (which, for the most part, provides little value) just go to &lt;a href=&quot;http://www.godaddy.com/ssl&quot;&gt;GoDaddy&lt;/a&gt; and get your $19.99 Turbo &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; certificate.&lt;/p&gt;
&lt;p&gt;The workflow will vary depending on your certificate authority; I&amp;#8217;ll describe how it works at GoDaddy.&lt;/p&gt;
&lt;p&gt;When you purchase your certificate, you get a credit that is good for one certificate. You then log into the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; Certificate part of the site and use the credit to request a certificate. The web form provides a form field into which you paste the text from the &lt;span class=&quot;caps&quot;&gt;CSR&lt;/span&gt; you generated in the previous step.&lt;/p&gt;
&lt;p&gt;When you submit the &lt;span class=&quot;caps&quot;&gt;CSR&lt;/span&gt;, the certificate authority will email the administrative contact for the domain to ask if they want to approve the request. This is how they verify that the certificate belongs to the domain. If you purchase a more expensive certificate, at this point they&amp;#8217;ll perform additional verification steps to ensure that the certificate belongs to who it says it belongs it.&lt;/p&gt;
&lt;p&gt;Once the &lt;span class=&quot;caps&quot;&gt;CSR&lt;/span&gt; is approved, you&amp;#8217;ll get an email with a link to download a zip file that contains the two certificate files you need to install on your server. One is your certificate, and will be named something like &amp;#8220;domainname.com.crt.&amp;#8221; The other is the &lt;em&gt;intermediate bundle&lt;/em&gt; certificate that establishes the chain that connects your certificate to the signing authority. In GoDaddy&amp;#8217;s case, this is gd_intermediate_bundle.crt.&lt;/p&gt;
&lt;p&gt;Now is a good time to make a backup of these files. The intermediate bundle is a standard file that you can usually get again, and you can request that your certificate authority re-issue your certificate file. But if you lose the key file, your certificate is worthless, and you&amp;#8217;ll have to purchase another one.&lt;/p&gt;
&lt;h2&gt;Configuring your web server&lt;/h2&gt;
&lt;p&gt;Now you need to configure your web server for &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;. Just how this is done depends on what server your using, its version, and how it was installed and configured. I&amp;#8217;ll describe how it works for a typical Apache 2.x configuration; you may need to adjust this for your situation.&lt;/p&gt;
&lt;p&gt;You should already have virtual host definition, either in your httpd.conf file or in an application-specific configuration file that is included into the main httpd.conf by reference. There are two kinds virtual host definitions: name-based, and IP address based. You can&amp;#8217;t use name-based virtual hosts with &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;, so you&amp;#8217;ll need to have a dedicated IP address for the site that is using &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;. If you only have one IP address for your server, you&amp;#8217;ll only be able to have one application. If you want to host multiple applications, your host should be able to provide you with multiple IP addresses.&lt;/p&gt;
&lt;p&gt;You&amp;#8217;ll need two virtual host blocks, one for the non-&lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; parts of the site, and another for the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; parts. The basic configuration should look something like this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;VirtualHost 123.456.789.123:80&amp;gt;

  Include conf/apps/domainname.conf.common

&amp;lt;/VirtualHost&amp;gt;

&amp;lt;VirtualHost 123.456.789.123:443&amp;gt;

  Include conf/apps/domainname.conf.common

  # SSL Engine Switch
  SSLEngine on

  # SSL Cipher Suite:
  SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

  # Server Certificate
  SSLCertificateFile /etc/httpd/conf/ssl.crt/domainname.com.crt

  # Server Private Key
  SSLCertificateKeyFile /etc/httpd/conf/ssl.key/domainname.key

  # Server Intermediate Bundle
  SSLCertificateChainFile /etc/httpd/conf/ssl.crt/gd_intermediate_bundle.crt

  # Set header to indentify https requests for Mongrel
  RequestHeader set X-Forwarded-Proto &quot;https&quot;

  BrowserMatch &quot;.*MSIE.*&quot; \
    nokeepalive ssl-unclean-shutdown \
    downgrade-1.0 force-response-1.0
  
  CustomLog logs/domainname.com-ssl_log \
    &quot;%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \&quot;%r\&quot; %b&quot;

&amp;lt;/VirtualHost&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s walk through this. The first virtual host block is essentially the same as what you&amp;#8217;d have without &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;, except that you have to specify an IP address (123.456.789.123 in this example). I&amp;#8217;ve put all the configuration that would normally go here, to set up the proxy to Mongrel and any mod_rewrite rules, into an include file, domainname.conf.common, which is not shown here. Doing so allows the same commands to be reused in the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; block.&lt;/p&gt;
&lt;p&gt;The second virtual host block defines the same IP address, but this time for port 443, which is the standard &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; port. First we include all the common configuration code to handle mongrel and so forth. Then, finally, comes the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; configuration directives. We need to turn on the &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; engine, specify the encryption to be used, and point to the three files we generated earlier: the key, the certificate, and the intermediate bundle. (The &lt;span class=&quot;caps&quot;&gt;CSR&lt;/span&gt; isn&amp;#8217;t needed once the certificate has been generated.) In this example, I&amp;#8217;ve shown them going in subdirectories of conf, but you can put them anywhere, as long as these pointers match the location.&lt;/p&gt;
&lt;p&gt;Next, we set the request header to tell mongrel when there is an https connection. Don&amp;#8217;t leave this out, or you&amp;#8217;ll have no end of confusing problems in your Rails code!&lt;/p&gt;
&lt;p&gt;Finally, there&amp;#8217;s a bit of config to keep Internet Explorer happy, and a custom log definition to log &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; accesses to a separate log file (this last bit is entirely optional).&lt;/p&gt;
&lt;p&gt;To test all this, enter&lt;/p&gt;
&lt;pre&gt;
apachectl configtest
&lt;/pre&gt;
&lt;p&gt;in an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; shell. This will check your config files for syntax errors without actually rebooting the server, so in case there&amp;#8217;s a problem you don&amp;#8217;t leave the server disabled while you sort out any errors.&lt;/p&gt;
&lt;p&gt;At last, you can now reboot Apache (sudo service httpd restart), and if everything is correct, you&amp;#8217;ll have an operating &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; server.&lt;/p&gt;
&lt;h2&gt;Tell your Rails app where to use &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;With the above setup done, you should be able to browse to any page in your application using either http:// or https://. You&amp;#8217;ll probably want to leave parts of the site unsecured, since &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; pages put extra load on the server, so you need a way to indicate which pages require &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;, and which don&amp;#8217;t.&lt;/p&gt;
&lt;p&gt;The ssl_requirement plugin, written by &lt;span class=&quot;caps&quot;&gt;DHH&lt;/span&gt; himself, makes this simple. Install the plugin:&lt;/p&gt;
&lt;pre&gt;
script/plugin install ssl_requirement
&lt;/pre&gt;
&lt;p&gt;And then include it at the top of your application.rb file, which effectively includes it in every controller:&lt;/p&gt;
&lt;pre&gt;
include SslRequirement
&lt;/pre&gt;
&lt;p&gt;Now all you need to do is specify, at the top of each controller, which controller actions require &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;:&lt;/p&gt;
&lt;pre&gt;
ssl_required  :login, :account, :payment, :cart
&lt;/pre&gt;
&lt;p&gt;Be sure to include in this list any create or update actions that process form data from &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; pages. The magic of this is that you don&amp;#8217;t need to change any links; any access to an action that requires &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; will automatically redirect to https://. If anyone tries to access a page that is supposed to be secure with an http:// link, they&amp;#8217;ll be redirected.&lt;/p&gt;
&lt;p&gt;You can also provide an &lt;code&gt;ssl_allowed&lt;/code&gt; declaration if there are actions that you want to be able to access either way. Such actions won&amp;#8217;t redirect to https:// but if that protocol is explicitly specified in a link, it will work.&lt;/p&gt;
&lt;h2&gt;Check your Ajax actions&lt;/h2&gt;
&lt;p&gt;For the most part, that&amp;#8217;s all there is to it on the Rails side. There&amp;#8217;s just one more thing that may require your attention: actions that service Ajax requests.&lt;/p&gt;
&lt;p&gt;On any page accessed with &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;, all Ajax requests must use &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;, or they will fail. To make this happen, all you need to do is include the names of the actions that service the requests in your &lt;code&gt;ssl_required&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;In some cases, you may have Ajax actions that have no code in the controller, but are just rendering &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; templates or other views. For these actions, you&amp;#8217;ll need to add an empty action definition block in the controller, and add the action name to the &lt;code&gt;ssl_required&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;One obscure case is the text_field_with_auto_complete helper. If you&amp;#8217;re using this in your view, you&amp;#8217;re probably also using the &lt;code&gt;auto_complete_for :model :field&lt;/code&gt; shortcut in your controller. This automatically produces an action to respond to the autocomplete requests. But since the action isn&amp;#8217;t explicitly defined, how do you tell it to require &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;? You just need to know what the automatically created action is named, which is &lt;code&gt;auto_complete_for_model_field&lt;/code&gt;. Just substitute the names of your model and field, and add this action name to your &lt;code&gt;ssl_required&lt;/code&gt; statement.&lt;/p&gt;
&lt;h2&gt;Check for mixed content&lt;/h2&gt;
&lt;p&gt;One last thing to watch out for is mixed content. If you&amp;#8217;re testing in Firefox, you won&amp;#8217;t notice it, but in IE, users will get a security warning if an &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; page accesses any non-secure content. You don&amp;#8217;t have to worry about links to images and so forth, as long as they&amp;#8217;ve been written as paths without the full domain name; those will automatically use the protocol of the main page. But if you have any full links, you&amp;#8217;ll need to make sure they are written as &amp;#8220;https://&amp;#8221; on any &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; page.&lt;/p&gt;
&lt;p&gt;One case where this problem can sneak in is with JavaScript snippets for services such as Google analytics. If you have a Google analytics link on your page, change it from &amp;#8220;http://www.google-analytics.com/urchin.js&amp;#8221; to &amp;#8220;&lt;strong&gt;https://ssl.&lt;/strong&gt;google-analytics.com/urchin.js&amp;#8221;. (Google has now change its analytics code so this isn&amp;#8217;t necessary if you&amp;#8217;re using their current code.) This will work fine on all pages, whether they use &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt; or not, and it will keep the analytics link from triggering the mixed content warning.&lt;/p&gt;
&lt;h2&gt;Now you have &lt;span class=&quot;caps&quot;&gt;SSL&lt;/span&gt;, but &amp;#8230;&lt;/h2&gt;
&lt;p&gt;Now your site can send pages in encrypted form, so they can&amp;#8217;t be snooped on by prying eyes along the path between your server and your user&amp;#8217;s computer. And the user can examine the certificate to see to whom it was granted, and know that the browser would warn them if the domain name didn&amp;#8217;t match.&lt;/p&gt;
&lt;p&gt;Of course, there&amp;#8217;s much more to keeping your users&amp;#8217; data secure. You need to ensure that all model requests are properly scoped, and for internal security, you need to make sure that confidential information isn&amp;#8217;t leaking out in your logs, exception reports, and backups.&lt;/p&gt;</body>
  <created-at type="datetime">2008-07-24T01:00:46-07:00</created-at>
  <created-by type="integer">1</created-by>
  <dy-schema-id type="integer" nil="true"></dy-schema-id>
  <dy-schema-type nil="true"></dy-schema-type>
  <filter-id nil="true"></filter-id>
  <flags type="integer">1</flags>
  <historic-id type="integer">8</historic-id>
  <id type="integer">6401</id>
  <kind-id type="integer">5019</kind-id>
  <lock-version type="integer">3</lock-version>
  <name>Using SSL in Rails Applications</name>
  <owner-id type="integer" nil="true"></owner-id>
  <owner-type nil="true"></owner-type>
  <published-at type="datetime">2008-04-05T17:00:00-07:00</published-at>
  <rating type="integer">4</rating>
  <ref-count type="integer">0</ref-count>
  <sequence type="integer">0</sequence>
  <status type="integer">0</status>
  <updated-at type="datetime">2009-03-23T22:59:57-07:00</updated-at>
  <updated-by type="integer">1</updated-by>
  <url nil="true"></url>
  <user-id type="integer">1</user-id>
  <version type="integer">4</version>
  <workflow-task-status-id type="integer" nil="true"></workflow-task-status-id>
</article-node>
