<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>default.aspx</title>
	<atom:link href="http://patrikc.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://patrikc.wordpress.com</link>
	<description>Asp.net, sql-server, säkerhet, prestanda, och seo</description>
	<lastBuildDate>Thu, 26 Nov 2009 20:37:26 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>sv</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='patrikc.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/6ce5b1d9cd519d38e8985b6b5facdae3?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>default.aspx</title>
		<link>http://patrikc.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://patrikc.wordpress.com/osd.xml" title="default.aspx" />
		<item>
		<title>Application warm-up för iis 7.5</title>
		<link>http://patrikc.wordpress.com/2009/11/26/application-warm-up-for-iis-7-5/</link>
		<comments>http://patrikc.wordpress.com/2009/11/26/application-warm-up-for-iis-7-5/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 20:36:56 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Asp.net]]></category>
		<category><![CDATA[Prestanda]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=701</guid>
		<description><![CDATA[Jag vill tipsa om ett plugin till iis 7.5 som heter application warm-up.
Varje gång man laddar upp nya filer, ändrar web.config eller en application pool recycle så måste koden kompileras om. På grund av det så tar det alltid extra lång tid för den första requesten direkt efter en uppladdning exempelvis. När man har flera [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=701&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Jag vill tipsa om ett plugin till iis 7.5 som heter <a href="http://www.iis.net/expand/applicationwarmup" target="_blank">application warm-up</a>.<span id="more-701"></span></p>
<p>Varje gång man laddar upp nya filer, ändrar web.config eller en application pool recycle så måste koden kompileras om. På grund av det så tar det alltid extra lång tid för den första requesten direkt efter en uppladdning exempelvis. När man har flera webbservrar och behöver göra underhåll så kommer det också att ta extra lång tid för den första requesten efter att man släppt på trafik igen.</p>
<p>Detta är givetvis inte bra eftersom användarna drabbas och upplever sidan som långsam.</p>
<p>Ett annat problem kan vara om man har en byggserver som bygger x gånger per dag, och när man vill gå in där för att testa så får man vänta några sekunder innan sidan visas. Det är givetvis irriterande.</p>
<p>Med application warm-up kan du se till att alltid ha förkompilerade sidor.<br />
Exempelvis kan man aktivera så den alltid kompilerar direkt efter varje recycle. Utöver det kan man själv specificera tidpunkter och/eller sidor man vill att application warm-up skall anropa. Kanske har man en tung sida som normalt ligger cachad länge, men första gången sidan laddas så tar det 10 sekunder att läsa in all data till cachen. Då kan man låta pluginet göra det, istället för att användarna skall behöva vänta den tiden.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/701/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/701/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/701/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/701/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/701/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/701/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/701/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/701/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/701/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/701/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=701&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/11/26/application-warm-up-for-iis-7-5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>Smarta kort med windows server 2008 och windows 7</title>
		<link>http://patrikc.wordpress.com/2009/11/22/smarta-kort-med-windows-server-2008-och-windows-7/</link>
		<comments>http://patrikc.wordpress.com/2009/11/22/smarta-kort-med-windows-server-2008-och-windows-7/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 15:13:10 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Säkerhet]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=662</guid>
		<description><![CDATA[Jag skriver mest om webbrelaterad säkerhet på denna blogg, men nyligen satt jag och labbade med att försöka logga in på windows med smarta kort. Jag tyckte det var onödigt komplicerat, så för andra som vill prova detta vill jag dela med mig av hur jag gjorde för att komma igång.
Innan man kan börja behöver [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=662&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Jag skriver mest om webbrelaterad säkerhet på denna blogg, men nyligen satt jag och labbade med att försöka logga in på windows med smarta kort. Jag tyckte det var onödigt komplicerat, så för andra som vill prova detta vill jag dela med mig av hur jag gjorde för att komma igång.<span id="more-662"></span></p>
<p>Innan man kan börja behöver man en del hårdvara. Jag valde att köpa kort och kortläsare från <a href="http://www.gemalto.com/" target="_blank">gemalto</a> och då deras gemalto .net-kort. De går att köpa exempelvis från <a href="http://www.smartjac.se" target="_blank">smartjac</a>.</p>
<p>När jag kopplade in kortläsaren i min windows 7-maskin så hittade den drivrutiner direkt. Men den hittade inga drivrutiner till kortet. För att hitta rätt drivrutiner lät jag bara kortet sitta i, gå till windows update och där tipsade den om drivrutiner till mitt kort. När klienten nu är klar är det dags att ge sig på servern.</p>
<p><img src="http://patrikc.files.wordpress.com/2009/11/screenshot099.jpg?w=271" alt="Inställningar för smartcardusers-gruppen" class="alignright size-medium wp-image-664" />För att få lite struktur så skapar jag först en grupp (SmartCardUsers) i active directory som skall kunna logga in med smart card. Det gör att det är väldigt enkelt att bara stoppa in nya användare efterhand.</p>
<p>För att få smarta kort att fungera måste man ha en tjänst som kan utfärda certifikat. I windows server 2008 heter den rollen active directory certificate services (ADCS) och det är alltså den du måste installera.</p>
<p>Man styr hur smarta kort skall hanteras genom GPO (adminstrative tools -&gt; group policy management). De ändringar man behöver göra för att komma igång är att först och främst konfigurera så att GPOn endast appliceras på den nyskapade gruppen SmartCardUsers. Det gör man genom Security Filtering och lägga dit gruppen och ta bort de andra. </p>
<p><img src="http://patrikc.files.wordpress.com/2009/11/screenshot1001.jpg" alt="GPO-inställningar för smartcardusers" width="480" height="279" class="alignnone size-full wp-image-672" /></p>
<p>Jag vill att alla användare som finns i gruppen automatiskt skall få sitt certifikat efter att de loggar in. En guide startar som kopierar certifikatet till kortet. För att aktivera det gick jag in i Group Policy Management och inställningen User configuration -&gt; Policies -&gt; Windows settings -&gt; Security settings -&gt; Public key policies -&gt; certificate services client &#8211; auto-enrollment. Jag aktiverar den och kryssar i &#8221;renew expired certificates&#8221; och &#8221;update certificates&#8221;.<br />
<img src="http://patrikc.files.wordpress.com/2009/11/screenshot101.jpg" alt="Certificate services client - auto-enrollment properties" width="480" height="338" class="alignnone size-full wp-image-666" /></p>
<p>För att administrera ADCS som vi installerade tidigare använder man administrative tools -&gt; certification authority. Där väljer jag att högerklicka på certificate templates och manage. Letar upp smartcard user och tar duplicate. Jag visar skärmdumpar på de ändringar jag har gjort, i övrigt är det standard. Observera att dessa inställningar gäller för gemalto.net, om du har ett annat kort kan du behöva göra vissa ändringar.</p>
<p><img src="http://patrikc.files.wordpress.com/2009/11/screenshot105.jpg?w=222" alt="Cryptography" width="222" height="300" class="alignnone size-medium wp-image-670" /><img src="http://patrikc.files.wordpress.com/2009/11/screenshot106.jpg?w=223" alt="Issuance requirements" width="223" height="300" class="alignnone size-medium wp-image-671" /><img src="http://patrikc.files.wordpress.com/2009/11/screenshot104.jpg?w=226" alt="Subject name" width="226" height="300" class="alignnone size-medium wp-image-669" /><img src="http://patrikc.files.wordpress.com/2009/11/screenshot103.jpg?w=224" alt="Request handling" width="224" height="300" class="alignnone size-medium wp-image-668" /><img src="http://patrikc.files.wordpress.com/2009/11/screenshot102.jpg?w=224" alt="General smard card settings" width="224" height="300" class="alignnone size-medium wp-image-667" /></p>
<p><img src="http://patrikc.files.wordpress.com/2009/11/screenshot108.jpg?w=224" alt="Security" title="ScreenShot108" width="224" height="300" class="alignright size-medium wp-image-689" />Den sista inställningen vi behöver göra på mallen är att bestämma vilka användare/grupper som skall kunna göra vad. I mitt exempel har jag konfigurerat gruppen gruppen SmartCardUsers att de får läsa mallen, samt använda den för enroll och autoenroll. Vilket då betyder att det kan rullas ut automatiskt till klienten.</p>
<p>Nu återstår det bara att aktivera mallen genom att högerklicka på certificate templates -&gt; new -&gt; certificate template to issue och sedan välja den nya mallen.</p>
<p><img src="http://patrikc.files.wordpress.com/2009/11/screenshot107.jpg" alt="Certificate template to issue" width="415" height="232" class="alignnone size-full wp-image-688" /></p>
<p>Du kan nu välja att uppdatera GPO-inställningarna hos klienten genom att köra &#8221;gpupdate /force&#8221; på klienten. Vid nästa inloggning bör en wizard starta som skriver certifikatet till kortet. Om den inte startar kan du prova att starta om certificate authority-tjänsten.</p>
<p>När allt nu är igång och fungerar så finns det mängder av inställningar att göra, exempelvis att användarna endast skall kunna logga in med smarta kort och inte via exempelvis lösenord. Det kan också vara bra att ställa in så att användarna blir utloggade om de plockar ut sitt smarta kort ur kortläsaren.</p>
<p>Om du vill gå in lite mer på djupet och kanske implementera smarta kort på allvar kan jag tipsa om <a href="http://www.microsoft.com/downloads/details.aspx?familyid=0BC67F4E-4FCF-4717-89E8-D0EE5E23A242&amp;displaylang=en" target="_blank">ett bra dokument från microsoft</a>. </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/662/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/662/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/662/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/662/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/662/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/662/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/662/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/662/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/662/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/662/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=662&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/11/22/smarta-kort-med-windows-server-2008-och-windows-7/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot099.jpg?w=271" medium="image">
			<media:title type="html">Inställningar för smartcardusers-gruppen</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot1001.jpg" medium="image">
			<media:title type="html">GPO-inställningar för smartcardusers</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot101.jpg" medium="image">
			<media:title type="html">Certificate services client - auto-enrollment properties</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot105.jpg?w=222" medium="image">
			<media:title type="html">Cryptography</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot106.jpg?w=223" medium="image">
			<media:title type="html">Issuance requirements</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot104.jpg?w=226" medium="image">
			<media:title type="html">Subject name</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot103.jpg?w=224" medium="image">
			<media:title type="html">Request handling</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot102.jpg?w=224" medium="image">
			<media:title type="html">General smard card settings</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot108.jpg?w=224" medium="image">
			<media:title type="html">ScreenShot108</media:title>
		</media:content>

		<media:content url="http://patrikc.files.wordpress.com/2009/11/screenshot107.jpg" medium="image">
			<media:title type="html">Certificate template to issue</media:title>
		</media:content>
	</item>
		<item>
		<title>Antixss med valfria html-taggar</title>
		<link>http://patrikc.wordpress.com/2009/11/12/antixss-med-valfria-html-taggar/</link>
		<comments>http://patrikc.wordpress.com/2009/11/12/antixss-med-valfria-html-taggar/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 20:28:14 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Asp.net]]></category>
		<category><![CDATA[Säkerhet]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=650</guid>
		<description><![CDATA[Antixss är ett bra säkerhetsbibliotek för att undvika problem med xss. Jag vill här visa hur du kan använda antixss i kombination med lite egen kod för att kunna styra vilka taggar som skall få visas på sidan och inte. Exempelvis kanske man vill tillåta &#60;img&#62;-taggen men inte &#60;div&#62; eller &#60;font&#62;.
När antixss släpptes i version [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=650&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://www.codeplex.com/antixss" target="_blank">Antixss</a> är ett bra säkerhetsbibliotek för att undvika problem med <a href="http://patrikc.wordpress.com/2009/05/13/xss-cross-site-scripting/">xss</a>. Jag vill här visa hur du kan använda antixss i kombination med lite egen kod för att kunna styra vilka taggar som skall få visas på sidan och inte. Exempelvis kanske man vill tillåta &lt;img&gt;-taggen men inte &lt;div&gt; eller &lt;font&gt;.<span id="more-650"></span></p>
<p>När antixss släpptes i <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=051ee83c-5ccf-48ed-8463-02f56a6bfc09&amp;displaylang=en" target="_blank">version 3.1</a> kom även en rad nyheter. Bland annat Security Runtime Engine (SRE) som är en http modul som du helt enkelt lägger in i ditt asp.net projekt, konfigurerar att den skall skydda dina sidor och då får du direkt ett bra skydd mot xss-attacker.</p>
<p>Jag vill gärna kunna vara mer flexibel och exempelvis skydda bara delar av en sida. Det är också möjligt med antixss version 3.1 genom metoderna GetSafeHtml() och GetSafeHtmlFragment(). </p>
<p>Det fina med GetSafeHtml är att den tar bort all eventuell skadlig kod, men förutom det så åtgärdar den även så all html blir korrekt.<br />
Om vi exempelvis skickar in <strong>&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</strong> till GetSafeHtml, så kommer den att returnera <strong>&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;</strong>. Detta gör den givetvis eftersom innehållet från en textbox kanske presenteras mitt i en sida bland andra div-element, vilket annars hade kunnat förstöra den övriga designen. Ett annat exempel är att den gör om <strong>&lt;p&gt;&lt;div&gt;&lt;/div&gt;&lt;/p&gt;</strong> till <strong>&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</strong>, detta eftersom en &lt;p&gt;-tagg inte kan innehålla en div.</p>
<p>Det jag tycker är synd med GetSafeHtml är att man inte själv kan konfigurera vilka taggar som skall skrivas ut som vanlig html-kod och vilka som skall köras genom HtmlEncode(). Jag satt precis med en uppgift där jag behövde den funktionen.</p>
<p>Lösningen blev att jag först kör HtmlEncode på alla taggar förutom de som explicit skall vara tillåtna. När det är gjort kör jag GetSafeHtml på det resultatet. Jag använder mig av <a href="http://patrikc.wordpress.com/2009/06/01/avancerade-reguljara-uttryck/">reguljära uttryck</a> för att välja ut html-taggarna.</p>
<p>I mitt exempel nedan kommer den att skriva ut taggarna <strong>&lt;div&gt;,&lt;img&gt;</strong> och <strong>&lt;br&gt;</strong> med attribut på ett säkert sätt. </p>
<pre class="brush: csharp;">
String data = &quot;exempeltext.&quot;; //Hämta data från valfri källa.

//Endast dessa taggar skall skrivas ut som html-kod, alla andra taggar skall
//säkras via HtmlEncode()
String tags = &quot;div|img|br&quot;;
String pattern = String.Concat(@&quot;&lt;(?!/?(&quot;, tags, @&quot;)( .*?|&gt;)).*?&gt;&quot;);

//Hämtar alla taggar som inte finns med i tags-variabeln
MatchCollection mc = Regex.Matches(data, pattern, RegexOptions.IgnoreCase);
foreach (Match match in mc)
{
    //Kör HtmlEncode på de taggar som hämtades med det reguljära uttrycket.
    data = data.Replace(match.Value, AntiXss.HtmlEncode(match.Value));
}

data = AntiXss.GetSafeHtml(data); //Kör GetSafeHtml på alla taggar som är kvar i vanlig html-form
</pre>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/650/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/650/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/650/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/650/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/650/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/650/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/650/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/650/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/650/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/650/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=650&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/11/12/antixss-med-valfria-html-taggar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>4 sätt att lösa prestandaproblem i sql-server &#8211; del 3</title>
		<link>http://patrikc.wordpress.com/2009/09/19/4-satt-att-losa-prestandaproblem-i-sql-server-del-3/</link>
		<comments>http://patrikc.wordpress.com/2009/09/19/4-satt-att-losa-prestandaproblem-i-sql-server-del-3/#comments</comments>
		<pubDate>Sat, 19 Sep 2009 05:12:34 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Prestanda]]></category>
		<category><![CDATA[SQL-Server]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=606</guid>
		<description><![CDATA[Detta är del 3 av 3 i en serie om att lösa prestandaproblem i sql-server.
Del 1 går igenom hur man letar upp prestandaproblem med profiler, del 2 går igenom DMV och del 3 går igenom performance monitor.

Perfmon
Förutom profiler och DMV:er är det bra att köra perfmon för att övervaka hur servern mår. Här kan man [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=606&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Detta är del 3 av 3 i en serie om att lösa prestandaproblem i sql-server.<br />
Del 1 går igenom hur man letar upp <a href="http://patrikc.wordpress.com/2009/09/15/4-satt-att-losa-prestandaproblem-i-sql-server-del-1/">prestandaproblem med profiler</a>, del 2 går igenom <a href="http://patrikc.wordpress.com/2009/09/17/4-satt-att-losa-prestandaproblem-i-sql-server-del-2/">DMV</a> och del 3 går igenom performance monitor.<br />
<span id="more-606"></span></p>
<h1>Perfmon</h1>
<p>Förutom profiler och DMV:er är det bra att köra perfmon för att övervaka hur servern mår. Här kan man ofta på hårdvarunivå bättre identifiera var prestandaproblemen ligger.<br />
Jag går igenom ett antal olika räknare (performance counters) och beskriver hur de skall läsas av och vad rimliga värden är.</p>
<p>De räknare som jag tycker är viktiga att övervaka på en sql-server-databas är följande<br />
Memory: Pages/sec<br />
Physical Disk: Avg. Disk Queue Length<br />
Physical Disk: Avg. Disk Sec/Read<br />
Physical Disk: Avg. Disk Sec/Write<br />
Processor: % Processor Time<br />
SQL Server Buffer: Buffer Cache Hit Ratio<br />
SQL Server General: User Connections  </p>
<p><strong>Memory: Pages/sec</strong><br />
Denna räknare visar hur mycket som går in eller ut från minne till disk. Du vill att denna räknare skall hålla sig under 20. Om den har ett snittvärde över 20 över en tidsperiod på 5 minuter så behöver du köpa mer minne till servern, alternativt konfigurera om din server och tilldela mer minne via sql-server-konfigurationen. Det är vanligt att man har toppar över 20 och det är helt normalt, det som är viktigt är att snittet inte går över 20.</p>
<p><strong>Physical Disk: Avg. Disk Queue Length</strong><br />
Denna räknare visar hur mycket kö det är mot dina diskar. Denna räknare finns även som läs- respektive skrivvariant som då endast visar hur mycket läs- eller skrivkö det är. De räknarna heter. Physical Disk: Avg. Disk Read Queue Length och Physical Disk: Avg. Disk Write Queue Length. Men de räknarna kan man börja använda först om man ser att man har ett övergripande problem.<br />
De flesta brukar säga att man har diskproblem om räknaren är över 2, men jag tycker nog att man börjar se problem redan när den överstiger 1-1½. Här kommer det också att bli toppar, exempelvis när den gör en <a href="http://msdn.microsoft.com/en-us/library/ms188748.aspx" target="_blank">checkpoint</a>. För denna räknare gäller även att den i snitt över en tidsperiod på 5 minuter inte skall överstiga 2, alternativt 1-1½ om du väljer att gå på min linje.</p>
<p>Det som är viktigt med denna räknare är dock att den måste beräknas, beroende på hur många diskar du har i ditt system. Om du exempelvis får att snittvärde för avg. disk queue length på ditt system är 7 och du har 10 diskar i ditt system så blir det alltså 7/10=0.7 vilket är mindre än 2 och alltså bör du inte ha några stora diskproblem. Oavsett raid-typ skall du alltid dela på antal diskar i systemet.</p>
<p>Om du vill räkna ut hur många IOs du har per disk skall du använda olika algoritmer beroende på vilken raid-typ.<br />
Raid 0 &#8212; I/Os per disk = (reads + writes) / antal diskar<br />
Raid 1 &#8212; I/Os per disk = (reads + (2 * writes)) / 2<br />
Raid 5 &#8212; I/Os per disk = (reads + (4 * writes)) / antal diskar<br />
Raid 10 &#8212; I/Os per disk = (reads + (2 * writes)) / antal diskar</p>
<p>reads får du fram genom räknaren Physical Disk: Avg. Disk Reads/Sec, writes får du fram genom räknaren Physical Disk: Avg. Disk Writes/Sec.</p>
<p><strong>Avg. Disk Sec/Read</strong><br />
Denna räknare talar om hur många sekunder i snitt det tog för disksystemet att returnera data.<br />
Här brukar man säga att<br />
Mindre än 10 ms &#8211; mycket bra<br />
Mellan 10 &#8211; 20 ms &#8211; okej<br />
Mellan 20 &#8211; 50 ms &#8211; långsamt, kan behöva tillsyn<br />
Större än 50 ms – stora I/O-problem</p>
<p><strong>Avg. Disk Sec/Write</strong><br />
Denna räknare talar om hur många sekunder i snitt det tog för disksystemet att skriva ner data. Här gäller samma avläsningsstrategi som för Avg. Disk Sec/Read.</p>
<p><strong>Processor: % Processor Time</strong><br />
Talar om hur mycket processorlast du har. Processorlasten bör inte överstiga 80%, om den gör det så tyder det på att processorn är överbelastad och att du bör utöka med fler eller snabbare processorer.</p>
<p><strong>SQL Server Buffer: Buffer Cache Hit Ratio</strong><br />
Denna talar om hur ofta sql-server går mot minnet istället för mot disk. I ett OLTP-system vill du att detta värde skall vara över 99% och absolut inte under 90%. Om den är under 90% så bör du köpa mer minne direkt. Om den är under 99% så bör du fundera på om mer ram kan hjälpa till, exempelvis genom att granska fler minnesräknare.</p>
<p><strong>SQL Server General: User Connections</strong><br />
Denna talar om hur många användaranslutningar som finns mot sql-server. Denna bör vara under 255 om du använder standardinställningen på Maximum Worker Threads i sql-server, eftersom den är 255. Om du har fler user connections än 255 bör du öka Maximum Worker Threads till ett värde som är högre än ditt högsta antal user connections. Om user connections är fler än Maximum Worker Threads så kommer sql-server att dela på trådar för varje anslutning vilket kan ge sämre prestanda. Notera dock att beroende på om du kör connection pool så kan många anslutningar ligga vilandes, så många gånger har man kanske fler användaranslutningar än vad sql-server egentligen behöver hantera.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/606/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/606/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/606/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/606/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/606/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/606/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/606/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/606/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/606/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/606/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=606&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/09/19/4-satt-att-losa-prestandaproblem-i-sql-server-del-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>Undersökning: Hur gör du vid felaktiga inloggningar?</title>
		<link>http://patrikc.wordpress.com/2009/09/17/undersokning-hur-gor-du-vid-felaktiga-inloggningar/</link>
		<comments>http://patrikc.wordpress.com/2009/09/17/undersokning-hur-gor-du-vid-felaktiga-inloggningar/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 14:12:49 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Undersökning]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=637</guid>
		<description><![CDATA[Det är dags att göra en undersökning, jag startar med en där jag själv har bytt åsikt från och till.
Det går att välja flera alternativ och även lägga till alternativ om man saknar något.
Hoppas ni vill vara med att svara, skicka gärna frågan vidare till andra.
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=637&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Det är dags att göra en undersökning, jag startar med en där jag själv har bytt åsikt från och till.<br />
Det går att välja flera alternativ och även lägga till alternativ om man saknar något.</p>
<p>Hoppas ni vill vara med att svara, skicka gärna frågan vidare till andra.</p>
<a name="pd_a_2004269"></a><div class="PDS_Poll" id="PDI_container2004269" style="display:inline-block;"></div><script type="text/javascript" language="javascript" charset="utf-8" src="http://static.polldaddy.com/p/2004269.js"></script>
		<noscript>
		<a href="http://answers.polldaddy.com/poll/2004269/">View This Poll</a><br/><span style="font-size:10px;"><a href="http://www.polldaddy.com">survey software</a></span>
		</noscript>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/637/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/637/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/637/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/637/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/637/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/637/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/637/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/637/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/637/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/637/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=637&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/09/17/undersokning-hur-gor-du-vid-felaktiga-inloggningar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>4 sätt att lösa prestandaproblem i sql-server &#8211; del 2</title>
		<link>http://patrikc.wordpress.com/2009/09/17/4-satt-att-losa-prestandaproblem-i-sql-server-del-2/</link>
		<comments>http://patrikc.wordpress.com/2009/09/17/4-satt-att-losa-prestandaproblem-i-sql-server-del-2/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 05:36:40 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Prestanda]]></category>
		<category><![CDATA[SQL-Server]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=603</guid>
		<description><![CDATA[Detta är del 2 av 3 i en serie om att lösa prestandaproblem i sql-server.
Del 1 går igenom hur man letar upp prestandaproblem med profiler, del 2 går igenom DMV och del 3 går igenom performance monitor.

DMV
I och med sql-server 2005 och introduktionen av DMV, dynamic management views så har det blivit enklare att lösa [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=603&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Detta är del 2 av 3 i en serie om att lösa prestandaproblem i sql-server.<br />
Del 1 går igenom hur man letar upp <a href="http://patrikc.wordpress.com/2009/09/15/4-satt-att-losa-prestandaproblem-i-sql-server-del-1/">prestandaproblem med profiler</a>, del 2 går igenom DMV och del 3 går igenom <a href="http://patrikc.wordpress.com/2009/09/19/4-satt-att-losa-prestandaproblem-i-sql-server-del-3/">performance monitor</a>.<br />
<span id="more-603"></span></p>
<h1>DMV</h1>
<p>I och med sql-server 2005 och introduktionen av DMV, dynamic management views så har det blivit enklare att lösa prestandaproblem. Med sql-server 2008 utökades antal DMV:er vilket ger ytterligare möjligheter att direkt få reda på var prestandaproblemen ligger.<br />
Jag listar här några bra och användbara DMV:er som fungerar i både sql-server 2005 och sql-server 2008. De flesta kommer from <a href="http://glennberrysqlperformance.spaces.live.com/Blog/" target="_blank">glenn berry</a> eller <a href="http://msdn.microsoft.com/en-us/library/dd672789.aspx" target="_blank">microsoft</a>.</p>
<h4>Hitta alla index som inte använts sedan senaste omstarten av sql-server</h4>
<p>Oanvända index vill vi inte ha eftersom det försämrar skrivprestanda</p>
<pre class="brush: sql;">
SELECT   OBJECT_NAME(object_id),
         i.name,
         i.index_id as index_id
FROM     sys.indexes i
WHERE    i.index_id NOT IN (SELECT s.index_id
                            FROM   sys.dm_db_index_usage_stats s
                            WHERE  s.object_id = i.object_id
                                   AND i.index_id = s.index_id
                                   AND database_id = DB_ID())
ORDER BY OBJECT_NAME(object_id) ASC
</pre>
<h4>Top 20 frågor som genererar mest cpu</h4>
<pre class="brush: sql;">
SELECT   TOP 20 qt.TEXT                                     AS 'SP Name',
                qs.total_worker_time                        AS 'TotalWorkerTime',
                qs.total_worker_time / qs.execution_count   AS 'AvgWorkerTime',
                qs.execution_count                          AS 'Execution Count',
                ISNULL(qs.execution_count / DATEDIFF(SECOND,qs.creation_time,GETDATE()),
                       0) AS 'Calls/Second',
                ISNULL(qs.total_elapsed_time / qs.execution_count,
                       0) AS 'AvgElapsedTime',
                qs.max_logical_reads,
                qs.max_logical_writes,
                DATEDIFF(MINUTE,qs.creation_time,GETDATE()) AS 'Age in Cache'
FROM     sys.dm_exec_query_stats AS qs
         CROSS APPLY sys.DM_EXEC_SQL_TEXT(qs.sql_handle) AS qt
WHERE    qt.dbid = DB_ID() -- Filter by current database
ORDER BY qs.total_worker_time DESC
</pre>
<h4>Top 20 frågor som genererar mest logical reads (minne)</h4>
<pre class="brush: sql;">
SELECT   TOP 20 qt.TEXT                                                          AS 'SP Name',
                total_logical_reads,
                qs.execution_count                                               AS 'Execution Count',
                total_logical_reads / qs.execution_count                         AS 'AvgLogicalReads',
                qs.execution_count / DATEDIFF(SECOND,qs.creation_time,GETDATE()) AS 'Calls/Second',
                qs.total_worker_time / qs.execution_count                        AS 'AvgWorkerTime',
                qs.total_worker_time                                             AS 'TotalWorkerTime',
                qs.total_elapsed_time / qs.execution_count                       AS 'AvgElapsedTime',
                qs.total_logical_writes,
                qs.max_logical_reads,
                qs.max_logical_writes,
                qs.total_physical_reads,
                DATEDIFF(MINUTE,qs.creation_time,GETDATE())                      AS 'Age in Cache',
                qt.dbid
FROM     sys.dm_exec_query_stats AS qs
         CROSS APPLY sys.DM_EXEC_SQL_TEXT(qs.sql_handle) AS qt
WHERE    qt.dbid = DB_ID() -- Filter by current database
ORDER BY total_logical_reads DESC
</pre>
<h4>Top 20 frågor som genererar mest physical reads (I/O)</h4>
<pre class="brush: sql;">
SELECT   TOP 20 qt.TEXT                                                          AS 'SP Name',
                qs.total_physical_reads,
                qs.total_physical_reads / qs.execution_count                     AS 'Avg Physical Reads',
                qs.execution_count                                               AS 'Execution Count',
                qs.execution_count / DATEDIFF(SECOND,qs.creation_time,GETDATE()) AS 'Calls/Second',
                qs.total_worker_time / qs.execution_count                        AS 'AvgWorkerTime',
                qs.total_worker_time                                             AS 'TotalWorkerTime',
                qs.total_elapsed_time / qs.execution_count                       AS 'AvgElapsedTime',
                qs.max_logical_reads,
                qs.max_logical_writes,
                DATEDIFF(MINUTE,qs.creation_time,GETDATE())                      AS 'Age in Cache',
                qt.dbid
FROM     sys.dm_exec_query_stats AS qs
         CROSS APPLY sys.DM_EXEC_SQL_TEXT(qs.sql_handle) AS qt
WHERE    qt.dbid = DB_ID() -- Filter by current database
ORDER BY qs.total_physical_reads DESC
</pre>
<h4>Top 20 frågor som genererar mest writes (I/O)</h4>
<pre class="brush: sql;">
SELECT TOP 20 qt.text AS 'SP Name', qs.total_logical_writes, qs.total_logical_writes/qs.execution_count AS 'AvgLogicalWrites',
    qs.total_logical_writes/DATEDIFF(Minute, qs.creation_time, GetDate()) AS 'Logical Writes/Min',
    qs.execution_count AS 'Execution Count',
    qs.execution_count/DATEDIFF(Second, qs.creation_time, GetDate()) AS 'Calls/Second',
    qs.total_worker_time/qs.execution_count AS 'AvgWorkerTime',
    qs.total_worker_time AS 'TotalWorkerTime',
    qs.total_elapsed_time/qs.execution_count AS 'AvgElapsedTime',
    qs.max_logical_reads, qs.max_logical_writes, qs.total_physical_reads,
    DATEDIFF(Minute, qs.creation_time, GetDate()) AS 'Age in Cache',
    qs.total_physical_reads/qs.execution_count AS 'Avg Physical Reads', qt.dbid
    FROM sys.dm_exec_query_stats AS qs
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
    WHERE qt.dbid = db_id() -- Filter by current database
    ORDER BY qs.total_logical_writes DESC
</pre>
<h4>En lista på index som har fler writes än reads.</h4>
<p>När ett index har fler skrivningar än läsningar så kan det tyda på ett dåligt val av index.</p>
<pre class="brush: sql;">
SELECT   OBJECT_NAME(s.object_id)                                AS [Table Name],
         i.name                                                  AS [Index Name],
         i.index_id,
         user_updates                                            AS [Total Writes],
         user_seeks + user_scans + user_lookups                  AS [Total Reads],
         user_updates - (user_seeks + user_scans + user_lookups) AS [Difference]
FROM     sys.dm_db_index_usage_stats AS s WITH (NOLOCK)
         INNER JOIN sys.indexes AS i WITH (NOLOCK)
           ON s.object_id = i.object_id
              AND i.index_id = s.index_id
WHERE    OBJECTPROPERTY(s.object_id,'IsUserTable') = 1
         AND s.database_id = DB_ID()
         AND user_updates &gt; (user_seeks + user_scans + user_lookups)
         AND i.index_id &gt; 1
ORDER BY [Difference] DESC,
         [Total Writes] DESC,
         [Total Reads] ASC;
</pre>
<p>Läs <a href="http://patrikc.wordpress.com/2009/09/19/4-satt-att-losa-prestandaproblem-i-sql-server-del-3/">del tre om performance monitor</a>.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/603/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/603/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=603&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/09/17/4-satt-att-losa-prestandaproblem-i-sql-server-del-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>Angående googles: let&#8217;s make the web faster</title>
		<link>http://patrikc.wordpress.com/2009/09/16/angaende-googles-lets-make-the-web-faster/</link>
		<comments>http://patrikc.wordpress.com/2009/09/16/angaende-googles-lets-make-the-web-faster/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 17:33:02 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Prestanda]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=616</guid>
		<description><![CDATA[Google har regelbundet utökat listan med användbara program sedan de lanserade google speed. Om du har missat det så är det dags att göra ett nytt besök.

Det är riktigt kul att se att de inte bara tipsar om sina egna program utan låter även andra stora företag vara med samt bidrag från vanliga användare.
Några av [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=616&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Google har regelbundet utökat <a href="http://code.google.com/speed/downloads.html" target="_blank">listan med användbara program</a> sedan de lanserade <a href="http://patrikc.wordpress.com/2009/06/05/gor-din-hemsida-snabbare-med-hjalp-fran-google-och-yahoo/">google speed</a>. Om du har missat det så är det dags att göra ett nytt besök.<br />
<span id="more-616"></span><br />
Det är riktigt kul att se att de inte bara tipsar om sina egna program utan låter även andra stora företag vara med samt bidrag från vanliga användare.</p>
<p>Några av de intressanta är:</p>
<p><a href="http://www.stevesouders.com/hammerhead" target="_blank">hammerhead</a> &#8211; hjälper dig att mäta laddtider på din hemsida<br />
<a href="http://mon.itor.us" target="_blank">mon.itor.us</a> &#8211; övervakar din hemsida och rapporterar om den skulle ligga nere, kan även installeras internt på dina servrar för att övervaka exempelvis cpu eller minne.<br />
<a href="http://www.stevesouders.com/spriteme" target="_blank">SpriteMe!</a> &#8211; gör om flera bilder till en enda bild och placerar ut dem via css (css sprites). Det gör att klienten behöver göra färre requests.<br />
<a href="http://wiki.github.com/stubbornella/oocss" target="_blank">oocss</a> &#8211; strukturera din css</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/616/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/616/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/616/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/616/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/616/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/616/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/616/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/616/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/616/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/616/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=616&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/09/16/angaende-googles-lets-make-the-web-faster/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>4 sätt att lösa prestandaproblem i sql-server &#8211; del 1</title>
		<link>http://patrikc.wordpress.com/2009/09/15/4-satt-att-losa-prestandaproblem-i-sql-server-del-1/</link>
		<comments>http://patrikc.wordpress.com/2009/09/15/4-satt-att-losa-prestandaproblem-i-sql-server-del-1/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 17:53:49 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Prestanda]]></category>
		<category><![CDATA[SQL-Server]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=596</guid>
		<description><![CDATA[När sajten går långsamt och orsaken är databasen kan man givetvis lösa problemet genom att köpa mer och/eller snabbare hårdvara. Ett billigare och enklare alternativ som man skall prova först är att undersöka om det går att optimera det befintliga på något sätt. Exempelvis genom att skapa eller modifiera index, skriva om lagrade procedurer eller [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=596&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>När sajten går långsamt och orsaken är databasen kan man givetvis lösa problemet genom att köpa mer och/eller snabbare hårdvara. Ett billigare och enklare alternativ som man skall prova först är att undersöka om det går att optimera det befintliga på något sätt. Exempelvis genom att skapa eller modifiera index, skriva om lagrade procedurer eller denormalisera tabeller för att få bättre prestanda. I dessa inlägg beskriver jag fyra användbara sätt att identifiera var flaskhalsen finns och därigenom också veta hur problemet bäst skall lösas.<br />
<span id="more-596"></span><br />
Jag har valt att dela upp inlägget i tre delar, de andra delarna publiceras de närmsta dagarna.<br />
Del 1 går igenom hur man letar upp prestandaproblem med profiler, del 2 går igenom <a href="http://patrikc.wordpress.com/2009/09/17/4-satt-att-losa-prestandaproblem-i-sql-server-del-2/">DMV</a> och del 3 går igenom <a href="http://patrikc.wordpress.com/2009/09/19/4-satt-att-losa-prestandaproblem-i-sql-server-del-3/">performance monitor</a>.</p>
<h1>Profiler</h1>
<p>Profiler är ett verktyg som kan logga allt som händer i databasen. Man kan välja vilka händelser och vilken data (kolumner) som skall loggas.</p>
<h4>Identifiera frågor som tar lång tid att exekvera</h4>
<p>Det är mycket enkelt att ta reda på vilka frågor som tar lång tid att köra. I mitt exempel kommer jag att logga alla frågor som tar längre tid än 1 sekund att köra. Det brukar generellt vara en bra start. Om frågan tar lång tid att köra så genererar den förmodligen mycket IO och/eller CPU vilket gör frågan till en bra optimeringskandidat.<br />
Börja med att starta sql-server profiler.</p>
<ol>
<li>Välj ”new trace”.</li>
<li>Välj ”standard” template.</li>
<li>Ta bort alla events förutom RPC:Completed och SQL:BatchCompleted.</li>
<li>Kontrollera att kolumnerna textdata, cpu, reads, writes, duration är ikryssade.</li>
<li>Klicka på kolumnen duration och mata in 1000 för ”greater than or equal”.</li>
<li>Klicka på ”run” och låt den köra en stund</li>
</ol>
<p>Relativt snart, beroende på hur ofta dina tunga frågor körs, bör du se data i fönstret. Om du inte får någon data kan det hända att alla dina frågor redan exekveras snabbare än 1 sekund, då kan du prova med 500ms eller 250ms.</p>
<h4>Identifiera frågor som tar mycket IO</h4>
<p>Det tidigare sättet identifierar enskilda frågor som tar lång tid att köra. Det är dock ännu vanligare att en fråga är relativt snabb men körs väldigt ofta och därmed tar väldigt mycket resurser från servern. För att hitta dessa frågor så loggar man alla frågor med profiler, sparar ner all data i en tabell och ställer frågor mot den. I vårt fall grupperar man på TextData-kolumnen som då innehåller hela sql-uttrycket.<br />
Starta sql-server profiler.</p>
<ol>
<li>Välj ”new trace”.</li>
<li>Välj ”standard” template.</li>
<li>Ta bort alla events förutom RPC:Completed och SQL:BatchCompleted.</li>
<li>Kontrollera att kolumnerna textdata, cpu, reads, writes, duration och starttime är ikryssade.</li>
<li>Klicka på textdata, mata in exec sp_reset_connection i not like.</li>
<li>Klicka på ”run” och låt den köra en stund. Gärna 24h, men beroende på trafikmängd kan det räcka med 1h. Har du färre än 100 000 poster efter 1h kan du köra ett tag till.</li>
</ol>
<p>När du har samlat tillräckligt mycket data så skall du spara ner det i en tabell &#8221;file -&gt; save as -&gt; trace table&#8221;.<br />
I det nedanstående kodexemplet jag har har jag döpt min tabell till trace. </p>
<p>Mitt kodexempel bygger på att det endast är lagrade procedurer som körs. Men om du har &#8221;vanliga&#8221; sql-frågor, kanske genererade av en ORM såsom nHibernate så måste du tvätta din trace på motsvarande sätt. Det jag gör nedan är att rensa bort allt förutom namnet på de lagrade procedurerna. Så om ett anrop såg ut såhär</p>
<p>exec myaccount.mystoredprocedure @Username = &#8216;patrikc&#8217;<br />
så kommer det efter tvätten att endast vara myaccount.mystoredprocedure<br />
Fört efter tvätten kan jag gruppera mina lagrade procedurer och få fram vilka procedurer som är mest kostsamma.</p>
<pre class="brush: sql;">
--rensa bort exec, hämta endast de poster som börjar på exec.
SELECT
	SUBSTRING(CAST(textdata AS VARCHAR(MAX)),CHARINDEX('exec ',CAST(textdata AS VARCHAR(MAX))) + 5, LEN(CAST(textdata AS VARCHAR(MAX))) - CHARINDEX('exec ',CAST(textdata AS VARCHAR(MAX))) - 4) AS textdata,
	cpu,
	reads,
	writes,
	duration
INTO
	#trace
FROM
	trace
WHERE
	CAST(textdata AS VARCHAR(MAX)) LIKE 'exec%' 

--vissa sps körs med sp_executesql så här raderar jag helt enkelt den informationen.
SELECT
	REPLACE(textdata,'sp_executesql N''EXEC ','') AS textdata,
	cpu,
	reads,
	writes,
	duration
INTO
	#trace2
FROM
	#trace 

--rensa bort allt efter det första mellanslaget (om det finns något mellanslag). gör en union mot de poster som saknar mellanslag.
SELECT
	SUBSTRING(textdata,1,CHARINDEX(' ',textdata) - 1) AS textdata,
    cpu,
    reads,
    writes,
    duration
INTO
	#trace3
FROM
	#trace2
WHERE
	CHARINDEX(' ',textdata) &gt; 0
UNION ALL
SELECT
	textdata,
    cpu,
    reads,
    writes,
    duration
FROM
	#trace2
WHERE
	CHARINDEX(' ',textdata) = 0 

--hämtar tiden som tracen kördes (används för att beräkna antal exekveringar per sekund)
DECLARE  @runtime REAL
SELECT
	@runtime = DATEDIFF(SECOND,MIN(starttime),MAX(starttime))
FROM
	trace

--grupperar alla poster på textdata och summerar cpu, reads, writes, duration. Sorterar på de poster med mest reads.
SELECT
	textdata,
	COUNT(0)                                             AS execcount,
	(CAST(COUNT(0) AS REAL) / CAST(@runtime AS REAL))    AS execpersec,
    SUM(duration)                                        AS sumduration,
    SUM(CAST(duration AS REAL)) / CAST(COUNT(0) AS REAL) AS avgduration,
    MAX(duration)                                        AS maxduration,
    SUM(reads)                                           AS sumreads,
    AVG(CAST(reads AS REAL))                             AS avgreads,
    MAX(reads)                                           AS maxreads,
    SUM(CAST(reads AS REAL)) / @runtime                  AS readspersec,
    SUM(writes)                                          AS sumwrites,
    AVG(CAST(writes AS REAL))                            AS avgwrites,
    MAX(writes)                                          AS maxwrites,
    SUM(CAST(writes AS REAL)) / @runtime                 AS writespersec,
    SUM(cpu)                                             AS sumcpu,
    AVG(CAST(cpu AS REAL))                               AS avgcpu,
    MAX(cpu)                                             AS maxcpu,
    SUM(CAST(cpu AS REAL)) / @runtime                    AS cpupersec
FROM
	#trace3
GROUP BY
	textdata
ORDER BY
	SUM(reads) DESC
</pre>
<p>Anledningen att jag väljer att i första hand sortera på de poster med mest reads är att det i de flesta fall är de som tar mest resurser från servern. Om man får ner de största posterna på reads så kan exempelvis duration gå ner på andra frågor, just eftersom diskköerna har gått ner.</p>
<p>Läs <a href="http://patrikc.wordpress.com/2009/09/17/4-satt-att-losa-prestandaproblem-i-sql-server-del-2/">del två om DMV</a>.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/596/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/596/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/596/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/596/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/596/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/596/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/596/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/596/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/596/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/596/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=596&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/09/15/4-satt-att-losa-prestandaproblem-i-sql-server-del-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>Skydda dina användares lösenord med hashfunktion och salt</title>
		<link>http://patrikc.wordpress.com/2009/08/23/skydda-dina-anvandares-losenord-med-hashfunktion-och-salt/</link>
		<comments>http://patrikc.wordpress.com/2009/08/23/skydda-dina-anvandares-losenord-med-hashfunktion-och-salt/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 19:03:42 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[Säkerhet]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=583</guid>
		<description><![CDATA[Det är inte sällan man läser om sajter som har blivit hackade där det ofta visat sig att lösenorden varit lagrade i klartext. Förutom det uppenbara problemet med att hackaren kan logga in på den berörda tjänsten med vilken användare som helst och möjlighet att förstöra, så skapar det indirekt problem även för andra tjänster [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=583&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Det är inte sällan man <a href="http://www.idg.se/2.1085/1.139967" target="_blank">läser</a> om <a href="http://www.idg.se/2.1085/1.138671" target="_blank">sajter</a> som har blivit <a href="http://www.idg.se/2.1085/1.147752" target="_blank">hackade</a> där det ofta visat sig att lösenorden varit lagrade i klartext. Förutom det uppenbara problemet med att hackaren kan logga in på den berörda tjänsten med vilken användare som helst och möjlighet att förstöra, så skapar det indirekt problem även för andra tjänster på internet. På grund av att användarna ofta använder samma lösenord för olika tjänster så kan en hacker exempelvis prova samma lösenord på andra tjänster, såsom gmail och hotmail och därmed ta över användares e-postadress också.<br />
<span id="more-583"></span></p>
<p>För att minska risken för ovanstående så skall sajtägare givetvis jobba för att få användare att ha olika lösenord. Det andra är att man som sajtägare skall ta sitt ansvar och skydda sina användares lösenord på ett bra sätt, och det är det jag skriver om i detta inlägg.</p>
<p>De komponenter som jag brukar förespråka skall finnas i ett bra lösenordssystem är: lösenord, hashfunktion, systemsalt, användarsalt, sammansättning, iterationer och versionshantering. Jag går igenom varje del för sig. Jag kommer i varje del beskriva varför det behövs.</p>
<h4>Lösenord</h4>
<p>Ditt lösenordssystem bör hjälpa användarna att välja ett bra lösenord. Sätt exempelvis krav på att lösenordet måste innehålla minst 8 tecken, varav minst en siffra och en icke alfanumerisk. Tänk på att kontrollera lösenordet både på klientsidan och serversidan. Läs gärna mitt inlägg om <a href="http://patrikc.wordpress.com/2009/06/01/avancerade-reguljara-uttryck/">avancerade reguljära uttryck</a> för att se exempel på hur det kan lösas. Kontrollera att lösenordet inte är samma som delar av e-postadress eller användarnamn.<br />
I samband med att användaren väljer lösenord bör du visa en hjälptext för användaren hur man väljer ett bra lösenord. Hjälptexten kan exempelvis innehålla:</p>
<ul>
<li>Välj ett lösenord som är svårt att gissa sig till</li>
<li>Välj ett lösenord som inte kan kopplas till dig eller någon annan familjemedlem exempelvis via namn, datum, smeknamn</li>
<li>Välj ett unikt lösenord som du inte använt på någon annan sajt</li>
</ul>
<p>I hjälptexten bör du dock inte ge riktlinjer om vilket lösenord man skall välja, då är risken stor att användaren kommer att skapa ett lösenord efter dina riktlinjer. Hjälptexten bör alltså <strong>inte</strong> innehålla fraser som:</p>
<ul>
<li>Välj ett svårt lösenord, exempelvis: Jua7;s..A&#8217;82</li>
<li>För att komma ihåg ditt lösenord, skapa en mening och ta de första bokstäverna till lösenordet, såsom. &#8221;Jag heter John och är 90 år gammal.&#8221;, skulle då bli JhJoä90åg.</li>
</ul>
<p>Varje del i detta inlägg kommer att utveckla lösenordssystemet och göra det säkrare. Jag vill därför via kod visa hur det kan se ut utan hashning.</p>
<p>password = &#8221;Ha%Ndl3(2~1&#8243;; // 11 tecken långt lösenord<br />
userController.SavePassword(password); // lösenordet lagras i klartext</p>
<h4>Hashfunktion</h4>
<p>Eftersom vi inte vill lagra lösenordet i klartext så vill vi hasha användarens lösenord innan det lagras i databasen. En hashfunktion är så kallad envägskryptering, vilket betyder att det inte går att återskapa originaldatat från den krypterade (eller hashade) strängen. Läs mitt inlägg om <a href="http://patrikc.wordpress.com/2009/07/17/introduktion-om-hur-en-hashfunktion-fungerar/">hur en hashfunktion fungerar</a> om du vill veta mer. </p>
<p>Du bör använda en så säker hashfunktion som är möjligt i just ditt projekt. Det kan exempelvis vara sha512. <a href="http://www.schneier.com/blog/archives/2005/06/more_md5_collis.html" target="_blank">md5</a> och <a href="http://www.schneier.com/blog/archives/2005/02/sha1_broken.html" target="_blank">sha1</a> anses vara osäkra i dag. Det är andra &#8211; säkrare &#8211; hashfunktioner på gång, såsom <a href="http://www.cs.technion.ac.il/~orrd/SHAvite-3/" target="_blank">sha-3</a> och <a href="http://www.skein-hash.info/" target="_blank">skein</a>. </p>
<p>password = &#8221;Ha%Ndl3(2~1&#8243;; // 11 tecken långt lösenord<br />
hash = sha512(password); // lösenordet hashas med sha512<br />
userController.SavePassword(hash); // lösenordet kan inte återskapas eftersom det är hashat</p>
<h4>Systemsalt</h4>
<p>Problemet med att enbart hasha lösenordet är att en eventuell hacker då kan skapa en databas som innehåller hashvärden av alla ord i en ordlista, och om inte det skulle räcka för att knäcka lösenord, så kan en hacker generera alla kombinationer upp till n tecken [a-zA-Z0-9] samt diverse icke alfanumeriska tecken. Det finns redan projekt för detta, exempelvis <a href="http://www.md5this.com/" target="blank">md5this</a> eller <a href="http://en.wikipedia.org/wiki/Rainbow_table" target="_blank">rainbow table</a> som inte ens behöver generera alla kombinationer. </p>
<p>Därför bör man lägga till ett salt som är samma för alla användare. Saltet bör vara långt, gärna över 20 tecken och ha samma krav som ett vanligt lösenord. Alltså bestå av siffror och icke alfanumeriska tecken.</p>
<p>Kodexempel</p>
<p>salt = &#8221;<lr)iJ@ZZ9Sb:AS,hL}@7FPw$JX%&#038;1L8#k/P]W$t0zUDz>PP&#8217;P0M`*4e&#038;5I@}&#8221; // långt salt<br />
password = &#8221;Ha%Ndl3(2~1&#8243;; // 11 tecken långt lösenord<br />
hash = sha512(salt + password); // skapar hash baserat på lösenord och salt<br />
userController.SavePassword(hash); // lösenordet kan inte återskapas eftersom det är hashat </p>
<h4>Användarsalt</h4>
<p>Problemet med att enbart hasha och använda systemsalt är att två användare som har valt samma lösenord har samma hashvärde i databasen. Detta kan utnyttjas av en hacker som kommer åt databasen. Exempelvis genom att generera nya användare med unika lösenord. Om den nyskapade användaren har samma hashvärde som en annan användare i databasen så har man knäckt den användarens lösenord.</p>
<p>För att motverka den möjligheten kan vi lägga till ett användarsalt som är unikt för varje användare. Då kommer hashvärdet inte att bli samma även om två användare har valt exakt samma lösenord.</p>
<p>usersalt = &#8221;<4VKfZK.^>KbT\G=sg[U^|Zz7hzfrh]vVA$ORE,b.Lbi42Gwk2flGy23PEOtB.&#8221;; // hämta användarsalt exempelvis från databasen<br />
salt = &#8221;<lr)iJ@ZZ9Sb:AS,hL}@7FPw$JX%&#038;1L8#k/P]W$t0zUDz>PP&#8217;P0M`*4e&#038;5I@}&#8221; // långt salt<br />
password = &#8221;Ha%Ndl3(2~1&#8243;; // 11 tecken långt lösenord<br />
hash = sha512(salt + password + usersalt); // skapar hash baserat på lösenord och salt<br />
userController.SavePassword(hash); // lösenordet kan inte återskapas eftersom det är hashat</p>
<h4>Sammansättning</h4>
<p>Hur man sätter samman sin hash kan variera. Anledningen till det är att om en hacker exempelvis kommer åt systemsalt och användarsalt så kan det användas för att göra en <a href="http://sv.wikipedia.org/wiki/Brute_force" target="_blank">brute force</a>. Problemet som hackern har är att han inte vet hur hashen är sammansatt. Se mitt kodexempel nedan för två exempel som kommer att resultera i två helt olika hashvärden, trots att alla komponenter systemsalt, lösenord och användarsalt är samma.</p>
<p>hash1 = sha512(salt + password + usersalt); // exempel på en sammansättning<br />
hash2 = sha512(usersalt + password + salt); // exempel på en annan sammansättning<br />
hash3 = sha512(sha512(usersalt + password) + salt); // exempel på en tredje sammansättning<br />
hash4 = sha512(salt + usersalt + sha512(password)); // exempel på en fjärde sammansättning</p>
<p>I de två första sammansättningarna har jag bara valt att byta plats på systemsalt och användarsaltet. Denna enkla förändring gör det dock genast svårare för en hacker att genom brute force få fram användarens lösenord. De två nedre är exempel där jag har valt att först skapa en hash och sedan skapa mitt slutgiltiga hashvärde baserat på den hashen och de återstående värdena.</p>
<h4>Iterationer</h4>
<p>Om en hacker får tag i hashvärdet, användarsaltet, systemsaltet samt sammansättningen så är det givetvis mycket illa. Men för att hackern skall kunna återskapa lösenord från dessa hashvärden så måste han köra brute force som helt enkelt skapar en hash baserat på alla möjliga kombinationer. När hackern lyckas skapa en hash som motsvarar den som fanns i databasen så har han fått fram lösenordet. Datorer kan prova flera tusen olika lösenord i sekunden, naturligtvis beroende på datorkraft men också på hashfunktion och sammansättning. Man vill försöka få ner antalet lösenord som kan testas per sekund, ett sätt är att lägga till iterationer som helt enkelt hashar lösenordet flera gånger. På det sättet måste även en hacker hasha lösenordet flera gånger vilket då tar processorkraft och i slutändan tar det längre tid för en hacker att göra brute force. </p>
<p>usersalt = &#8221;<4VKfZK.^>KbT\G=sg[U^|Zz7hzfrh]vVA$ORE,b.Lbi42Gwk2flGy23PEOtB.&#8221;; // hämta användarsalt exempelvis från databasen<br />
salt = &#8221;<lr)iJ@ZZ9Sb:AS,hL}@7FPw$JX%&#038;1L8#k/P]W$t0zUDz>PP&#8217;P0M`*4e&#038;5I@}&#8221; // långt salt<br />
password = &#8221;Ha%Ndl3(2~1&#8243;; // 11 tecken långt lösenord<br />
hash = sha512(salt + password + usersalt); // skapar hash baserat på lösenord och salt<br />
for (int i=0;i<1000;i++){<br />
    hash = sha512(hash); // skapar ny hash av det föregående hashvärdet<br />
}<br />
userController.SavePassword(hash); // lösenordet kan inte återskapas eftersom det är hashat</p>
<p>I ovanstående exempel hashar jag hashvärdet 1000 gånger. Du kan vilja hasha fler gånger. <a href="http://www.rsa.com/rsalabs/node.asp?id=2127" target="_blank">RSA PKCS #5</a> rekommenderar minst <a href="ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-5v2/pkcs5v2_1.pdf" target="_blank">1000 iterationer</a>.</p>
<h4>Versionshantering</h4>
<p>Du vill hela tiden se över ditt lösenordssystem. Kanske använder du en hashfunktion som är gammal och osäker, såsom <a href="http://www.microsoft.com/technet/security/advisory/961509.mspx" target="_blank">md5</a>. Eller så vill du ändra sammansättning, systemsalt eller iterationer. Oavsett vad så vill du kunna ändra. Därför är det bra att versionshantera dina användares lösenord. Det innebär att trots att du har bytt lösenordssystem så kan en användare logga in via det gamla systemet och när han gör det så skapar du en ny lösenordshash för användaren och nästa gång användaren loggar in görs det genom det nya lösenordssystemet. En annan fördel med detta är att du efter x dagar/veckor/månader kan stänga av alla användare som inte har uppgraderat sitt lösenord till det nya systemet, om du exempelvis har hittat en säkerhetslucka i ditt system eller om en hacker har gjort det.</p>
<p>passwordVersion = &#8221;1.2&#8243;;<br />
userController.SavePassword(hash, passwordVersion); // lösenordet sparas på samma sätt som vi gjort förut men denna gång skickar vi med versionsnummer som också lagras i databasen</p>
<h4>Men om användaren glömt lösenordet?</h4>
<p>En vanlig fråga som dyker upp i samband med hashning av lösenord, är hur man skall kunna skicka lösenordet till användaren om denna har glömt det. Som jag ser det så skall man aldrig skicka ett lösenord till en användare. Anledningen är lösenordet för det första skall vara hashat och för det andra är det vanligt att lösenordet skickas okrypterat via e-post som ligger lagrat i all evig framtid. Detta gör att om användarens e-post blir hackat och användaren inte har bytt lösenord så kommer hackern åt tjänsten.</p>
<p>Istället rekommenderar jag ett lösenordsåterställningssystem som baseras på två nycklar som är unika för varje användare. Man kan exempelvis skicka en länk (via e-post) som ser ut såhär:<br />
<strong>restore_password.aspx?userid=1&amp;key1=1C7D40F0-900B-11DE-AC98-81E455D89593&amp;key2=255D0FFC-900B-11DE-938D-A5E455D89593</strong>.<br />
Dessa två nycklar skall endast vara giltiga en viss tid, exempelvis 24 timmar samt bli ogiltiga direkt när användaren har bytt lösenord. Detta tvåkomponentsystem gör det i praktiken väldigt svårt att gissa sig till nycklarna och därmed svårt att hacka. </p>
<p>När användaren följer länken så kommer den till en krypterad sida (https) där han kan välja sitt nya lösenord.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/583/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/583/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/583/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/583/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/583/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/583/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/583/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/583/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/583/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/583/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=583&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/08/23/skydda-dina-anvandares-losenord-med-hashfunktion-och-salt/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
		<item>
		<title>Nyheter i SQL-Server 2008</title>
		<link>http://patrikc.wordpress.com/2009/08/17/nyheter-i-sql-server-2008/</link>
		<comments>http://patrikc.wordpress.com/2009/08/17/nyheter-i-sql-server-2008/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 12:16:41 +0000</pubDate>
		<dc:creator>patrik</dc:creator>
				<category><![CDATA[SQL-Server]]></category>

		<guid isPermaLink="false">http://patrikc.wordpress.com/?p=573</guid>
		<description><![CDATA[Det finns några intressanta nyheter för utvecklare i sql-server 2008. Jag vill här visa några exempel.

Tilldela värde till variabler redan vid deklarationen
Innan sql-server 2008 var man tvungen att först deklarera en variabel via declare @var int för att sedan tilldela variabeln via set @var = 42. Det har nu blivit möjligt att tilldela ett värde [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=573&subd=patrikc&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Det finns några intressanta nyheter för utvecklare i sql-server 2008. Jag vill här visa några exempel.<br />
<span id="more-573"></span></p>
<h4>Tilldela värde till variabler redan vid deklarationen</h4>
<p>Innan sql-server 2008 var man tvungen att först deklarera en variabel via <strong>declare @var int</strong> för att sedan tilldela variabeln via <strong>set @var = 42</strong>. Det har nu blivit möjligt att tilldela ett värde direkt vid deklarationen. Exempelvis.</p>
<pre class="brush: sql;">declare @var int = 42</pre>
<h4>Mata in flera rader samtidigt i en insert</h4>
<p>När man skapar poster i en tabell med insert så har det tidigare krävts ganska mycket kod, varav det mesta varit repetitivt. Man skrev ofta på följande sätt.</p>
<pre class="brush: sql;">insert into mytable values (1, 'first')
insert into mytable values (2, 'second')
insert into mytable values (3, 'third')</pre>
<p>Det har nu blivit minte repetitivt genom att man bara behöver skriva <strong>insert into mytable values</strong> en gång. Nedanstående kod resulterar alltså i tre nya poster i tabellen.</p>
<pre class="brush: sql;">insert into mytable
  values (1, 'first'), (2, 'second'), (3, 'third')</pre>
<h4>Smidigare tilldelning</h4>
<p>Det har länge varit möjligt att öka eller minska en variabels värde genom += eller -= i c#. Nu kommer samma möjlighet i sql. Istället för att skriva.</p>
<pre class="brush: sql;">update mytable set price = price + 10 where product = 'first'</pre>
<p>så kan vi nu skriva:</p>
<pre class="brush: sql;">update mytable set price += 10 where product = 'first'</pre>
<p>De nya operatorerna är:  +=, -=, *=, /= och %=.</p>
<p>Nyheterna som jag beskrivit hittills handlar mycket om att få ner mängden kod som behöver skrivas för att utföra något. Det är inte bara bra för utvecklarna, det är också bra för prestandan eftersom det blir mindre nätverkstrafik.</p>
<h4>Bättre datumhantering</h4>
<p>Det finns nu fler datatyper för att hantera datum.<br />
Exempelvis finns datetime2 som har en noggrannhet på 100 nanosekunder, exempelvis <strong>2009-08-17 11:14:45.3875725</strong>. Detta är att jämföra med datetime vars noggrannhet endast är 3.33 millisekunder, exempelvis <strong>2009-08-17 11:14:45.387</strong>.</p>
<p>Förutom ovanstående så finns det två nya datatyper i form av date och time.<br />
<strong>Datetime</strong> lagras i form av 8 bytes.<br />
<strong>Datetime2</strong> lagras med 7 bytes som standard, men kan ta upp till 8 bytes om fler decimaler används.<br />
<strong>Date</strong> lagras med 3 bytes.<br />
<strong>Time</strong> lagras med 5 bytes.</p>
<p>Ofta när man jobbar med datum har man ingen användning av tiden, därför är det bra att nu kunna skapa kolumner som bara är datum. Dessutom har det ibland varit problematiskt att hämta ut poster baserat på datum. Detta eftersom sql-server avrundar. Som exempel kan vi ta nedanstående.</p>
<pre class="brush: sql;">CREATE TABLE [DateTest](
	[PostDate] [datetime]
)

INSERT INTO DateTest VALUES
	('2009-08-08 23:59:59'),
	('2009-08-09 00:00:00'),
	('2009-08-10 00:00:00'),
	('2009-08-10 00:00:01')

SELECT * FROM DateTest WHERE PostDate BETWEEN '2009-08-09' AND '2009-08-10'
</pre>
<p>Ovanstående SELECT resulterar i två poster. Alltså <strong>2009-08-09 00:00:00</strong> och <strong>2009-08-10 00:00:00</strong>. Här förväntar vi oss förmodligen att få tre poster där PostDate är antingen 2009-08-09 eller 2009-08-10, men istället får vi alla datum som är mellan eller lika med 2009-08-09 00:00:00 och 2009-08-10 00:00:00 och missar därmed 2009-08-10 00:00:01. Ovanstående har många gånger orsakat buggar i diverse applikationer. Med datatypen date blir det genast enklare.</p>
<pre class="brush: sql;">CREATE TABLE [DateTest](
	[PostDate] [date]
)

INSERT INTO DateTest VALUES
	('2009-08-08 23:59:59'),
	('2009-08-09 00:00:00'),
	('2009-08-10 00:00:00'),
	('2009-08-10 00:00:01')

SELECT * FROM DateTest WHERE PostDate BETWEEN '2009-08-09' AND '2009-08-10'
</pre>
<p>Ovanstående kod returnerar alla tre poster. Dessutom sparar vi 5 bytes.</p>
<h4>Merge</h4>
<p>Merge används för att jämföra två datamängder och sedan köra insert/update/delete baserat på vad man har definierat. Det kan exempelvis användas istället för att göra en så kallad UPSERT som kortfattat innebär att man först kontrollerar om posten finns och gör en update eller insert baserat på det. Exempel på en upsert kan vara.</p>
<pre class="brush: sql;">IF EXISTS (SELECT * FROM UPSERTEXAMPLE WHERE name = 'john doe')
BEGIN
	UPDATE UPSERTEXAMPLE SET name = 'john doe 2' WHERE name = 'john doe'
END
ELSE
BEGIN
	INSERT INTO UPSERTEXAMPLE VALUES ('john doe 2')
END
</pre>
<p>Med merge kan man istället skriva.</p>
<pre class="brush: sql;">MERGE UPSERTEXAMPLE as t --target
USING (SELECT 'john doe' as name) as s --source
ON t.name = s.name
WHEN MATCHED THEN
   UPDATE SET t.name = 'john doe 2'
WHEN NOT MATCHED BY TARGET THEN
   INSERT VALUES(s.name);</pre>
<p>Notera att semikolon i slutet är obligatoriskt för merge.<br />
Merge fungerar som så att man först anger ett mål (target) och sedan en källa (source) samt deras relation i form av en join. I vårt fall joinar vi t.name och s.name. Sedan lägger man in ett antal villkor. Om båda posterna finns i både källan och målet så genomförs en update. Om posten inte finns i målet så lägger man till posten med en insert. Vid de prestandamätningar som jag har gjort på merge så är merge långsammare än en upsert. Men om det är flera poster som skall jämföras så blir merge givetvis användbar eftersom den är set-baserad.</p>
<p>Ett annat tillfälle då merge kan vara bra är om man vill synkronisera två tabeller. I mitt exempel har jag två likadana tabeller. Den ena är för produktion, och den andra för utveckling. Det rör sig om en tabell med texter. Om man vill synkronisera dessa tabeller så informationen är identisk kan man göra på följande sätt.</p>
<p>Vi börjar med att skapa tabellerna och mata in exakt samma innehåll.</p>
<pre class="brush: sql;">CREATE TABLE productioncontent (contentkey int primary key, content varchar(max))
CREATE TABLE developmentcontent (contentkey int primary key, content varchar(max))

INSERT INTO productioncontent values (1, 'text'), (2, 'text'), (3, 'text')
INSERT INTO developmentcontent values (1, 'text'), (2, 'text'), (3, 'text')
</pre>
<p>Sedan gör vi diverse ändringar i produktionstabellen.</p>
<pre class="brush: sql;">
INSERT INTO productioncontent values (4, 'text')
UPDATE productioncontent SET content = 'new text' where contentkey = 3
DELETE FROM productioncontent WHERE contentkey = 2
</pre>
<p>Nu vill vi med merge se till att alla ändringar vi gjorde nyss på produktionstabellen även kommer till utvecklingstabellen.</p>
<pre class="brush: sql;">
MERGE developmentcontent as d --target
USING productioncontent as p --source
ON d.contentkey = p.contentkey
WHEN MATCHED AND d.content &lt;&gt; p.content THEN
   UPDATE SET d.content = p.content
WHEN NOT MATCHED BY SOURCE THEN
   DELETE
WHEN NOT MATCHED BY TARGET THEN
   INSERT VALUES(p.contentkey, p.content);
</pre>
<p>Det som skiljer ovanstående från föregående exempel är att vi endast gör en update när posterna matchar (eftersom vi kör join på contentkey) och content är förändrat. Utöver det gör vi en delete och raderar därmed posten när raden inte matchar i källan (source). Vi utför en insert när posten inte finns i målet (target). Läs gärna mer om <a href="http://msdn.microsoft.com/en-us/library/bb510625.aspx" target="_blank">merge</a> på microsofts hemsida.</p>
<h4>Table valued parameters</h4>
<p>Table valued parameters gör det möjligt att skicka in en hel kollektion från .net direkt till sql-server. Tidigare har man behövt köra en insert/update/delete i taget eller skicka in exempelvis en kommaseparerad sträng att jobba vidare med. Förutom enklare hantering i både .net-koden och på databassidan så blir det bättre prestanda eftersom färre databasanrop krävs. Jag har skrivit ett längre blogginlägg om <a href="http://patrikc.wordpress.com/2009/08/14/table-valued-parameters-i-sql-server-2008/">table valued parameters</a>, läs det gärna för att lära dig mer.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/patrikc.wordpress.com/573/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/patrikc.wordpress.com/573/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/patrikc.wordpress.com/573/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/patrikc.wordpress.com/573/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/patrikc.wordpress.com/573/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/patrikc.wordpress.com/573/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/patrikc.wordpress.com/573/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/patrikc.wordpress.com/573/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/patrikc.wordpress.com/573/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/patrikc.wordpress.com/573/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=patrikc.wordpress.com&blog=420021&post=573&subd=patrikc&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://patrikc.wordpress.com/2009/08/17/nyheter-i-sql-server-2008/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">patrik</media:title>
		</media:content>
	</item>
	</channel>
</rss>