۱۳۸۸/۰۹/۰۶

استفاده از API ترجمه گوگل


مطابق Ajax API ترجمه گوگل، براي ترجمه يك متن بايد محتويات آدرس زير را تحليل كرد:
http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q={0}&langpair={1}|{2}
كه در آن پارامتر اول، متن مورد نظر، پارامترهاي 1 و 2 زبان‌هاي مبدا و مقصد مي‌باشند. براي دريافت اطلاعات، ذكر ارجاع دهنده الزامي است (referrer)، اما ذكر كليد API گوگل اختياري مي‌باشد (كه هر فرد مي‌تواند كليد خاص خود را از گوگل دريافت كند).
بنابراين براي استفاده از آن تنها كافي است اين URL را تشكيل داده و سپس محتويات خروجي آن‌را آناليز كرد. فرمت نهايي دريافت شده از نوع JSON است. براي مثال اگر hello world! را به اين سرويس ارسال نمائيم،‌ خروجي نهايي JSON‌ دريافت شده به صورت زير خواهد بود:

//{\"responseData\": {\"translatedText\":\"سلام جهان!\"}, \"responseDetails\": null, \"responseStatus\": 200}

در كتابخانه‌ي System.Web.Extensions.dll دات نت فريم ورك سه و نيم، كلاس JavaScriptSerializer براي اين منظور پيش بيني شده است. تنها كافي است به متد Deserialize آن، متن JSON دريافتي را پاس كنيم:

GoogleAjaxResponse result =
new JavaScriptSerializer().Deserialize<GoogleAjaxResponse>(jsonGoogleAjaxResponse);

براي اينكه عمليات نگاشت اطلاعات متني JSON به كلاس‌هاي دات نتي ما با موفقيت صورت گيرد، مي‌توان خروجي JSON گوگل را به شكل زير نمايش داد:

//ResponseData.cs file
public class ResponseData
{
public string translatedText { get; set; }
}

//GoogleAjaxResponse.cs file
using System.Net;

/// <summary>
/// كلاسي جهت نگاشت اطلاعات جي سون دريافتي به آن
/// </summary>
public class GoogleAjaxResponse
{
public ResponseData responseData { get; set; }
public object responseDetails { get; set; }
public HttpStatusCode responseStatus { get; set; }
}
با اين توضيحات، كلاس نهايي ترجمه گوگل ما به شكل زير خواهد بود:

using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Script.Serialization;

//{\"responseData\": {\"translatedText\":\"سلام جهان!\"}, \"responseDetails\": null, \"responseStatus\": 200}

public class CGoogleTranslator
{
#region Fields (1)

/// <summary>
/// ارجاع دهنده
/// </summary>
private readonly string _referrer;

#endregion Fields

#region Constructors (1)

/// <summary>
/// مطابق مستندات نياز به يك ارجاع دهنده اجباري مي‌باشد
/// </summary>
/// <param name="referrer"></param>
public CGoogleTranslator(string referrer)
{
_referrer = referrer;
}

#endregion Constructors

#region Properties (2)

/// <summary>
/// ترجمه از زبان
/// </summary>
public CultureInfo FromLanguage { get; set; }

/// <summary>
/// ترجمه به زبان
/// </summary>
public CultureInfo ToLanguage { get; set; }

#endregion Properties

#region Methods (2)

// Public Methods (1)

/// <summary>
/// ترجمه متن با استفاده از موتور ترجمه گوگل
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string TranslateText(string data)
{
//ساخت و انكدينگ آدرس مورد نظر
string url =
string.Format(
"http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q={0}&langpair={1}|{2}",
HttpUtility.UrlEncode(data), //needs a ref. to System.Web.dll
FromLanguage.TwoLetterISOLanguageName,
ToLanguage.TwoLetterISOLanguageName
);

//دريافت اطلاعات جي سون از گوگل
string jsonGoogleAjaxResponse = fetchWebPage(url);

//needs a ref. to System.Web.Extensions.dll
//نگاشت اطلاعات جي سون دريافت شده به كلاس مرتبط
GoogleAjaxResponse result =
new JavaScriptSerializer().Deserialize<GoogleAjaxResponse>(jsonGoogleAjaxResponse);

if (result != null && result.responseData != null && result.responseStatus == HttpStatusCode.OK)
{
return result.responseData.translatedText;
}
return string.Empty;
}
// Private Methods (1)

/// <summary>
/// دريافت محتويات جي سون بازگشتي از گوگل
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
string fetchWebPage(string url)
{
try
{
var uri = new Uri(url);
if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)
{
var request = WebRequest.Create(uri) as HttpWebRequest;
if (request != null)
{
request.Method = WebRequestMethods.Http.Get;
request.Referer = _referrer;
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.0; ; rv:1.8.0.7) Gecko/20060917 Firefox/1.9.0.1";
request.AllowAutoRedirect = true;
request.Timeout = 1000 * 300;
request.KeepAlive = false;
request.ReadWriteTimeout = 1000 * 300;
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

using (var response = request.GetResponse() as HttpWebResponse)
{
if (response != null)
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd().Trim();
}
}
}
}
}
return string.Empty;
}
catch (Exception ex)
{
Console.WriteLine(String.Format("fetchWebPage: {0} >> {1}", ex.Message, url), true);
return string.Empty;
}
}

#endregion Methods
}
مثالي در مورد نحوه‌ي استفاده از آن براي ترجمه يك متن از انگليسي به فارسي:

string res = new CGoogleTranslator("http://vahidnasiri.blogspot.com/")
{
FromLanguage = CultureInfo.GetCultureInfo("en-US"),
ToLanguage = CultureInfo.GetCultureInfo("fa-IR")
}.TranslateText("Hello world!");

۱۳۸۸/۰۹/۰۴

آشنايي با الگوي MVVM


حدود يك سال قبل الگوي MVVM زياد معروف نبود (Model-View-ViewModel pattern). اما در 6 ماه اخير، اين الگو به يك متدولوژي جدي توسعه برنامه‌هاي WPF و سيلورلايت تبديل شده. نمي‌شود به يك وبلاگ خوب WPF سر زد و خبري از اين روش نباشد. حتي فريم ورك‌هايي هم براي آن طراحي شده كه ليست آن‌ها را در اين مقاله مي‌توانيد مشاهده نمائيد.

مزاياي اين الگو چيست؟
  • جدا سازي Model و View
  • توليد كدهايي با قابليت تست بالا
  • فايل‌هاي code-behind ايي با حداقل كد
و ...

اگر علاقمند به آشنايي با اين الگوي طراحي باشيد ويديوي آموزشي زير در طي يك ساعت و نيم به توضيح اين مطلب پرداخته است.




ماخذ

۱۳۸۸/۰۹/۰۳

IIS7 و آپلود فايل‌هاي حجيم


با استفاده از IIS6 ويندوز سرور 2003 و تنظيمات ويژه در web.config يك برنامه ASP.Net، حداكثر مي‌توان يك فايل 2 گيگابايتي را آپلود كرد (جهت مصارف اينترانتي). براي مثال:
<system.web>
<httpRuntime maxRequestLength="2097151" executionTimeout="900" />
</system.web>
2097151 كيلوبايت حداكثر مقداري است كه اينجا مي‌توان تنظيم كرد و بيش از اين با خطاي زير متوقف خواهيم شد:

Parser Error Message: The value for the property 'maxRequestLength' is not valid. The error is: The value must be inside the range 0-2097151.

اين محدوديت در IIS7 برطرف شده است كه تنظيمات آن در وب كانفيگ به صورت زير مي‌باشد:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295" />
</requestFiltering>
</security>
</system.webServer>

در اينجا maxAllowedContentLength بر حسب بايت است و نه همانند maxRequestLength برحسب كيلوبايت (كه در IIS7 هيچ تاثيري نخواهد داشت).
البته تنظيمات فوق در اينجا به پايان نمي‌رسند زيرا بر اساس تنظيمات امنيتي IIS7، كاربران مجاز به اعمال تنظيمات شخصي خود نيستند و خطاي زير را دريافت خواهند كرد:
The requested page cannot be accessed because the related configuration data for the page is invalid
و يا

The request filtering module is configured to deny a request that exceeds the request content length

براي اين منظور بايد دستور زير را با دسترسي مديريتي در خط فرمان اجرا نمود:
براي يك برنامه خاص:
%windir%\system32\inetsrv\appcmd set config "Default Web Site/<your app>" -section:requestFiltering -requestLimits.maxAllowedContentLength:4294967295

و يا براي تمام برنامه‌ها:
%windir%\system32\inetsrv\appcmd set config -section:requestFiltering -requestLimits.maxAllowedContentLength:4294967295

و يا فايل زير را يافته:
%windir%\System32\inetsrv\config\applicationHost.config
در آن سطر زير را
<section name="requestFiltering" overrideModeDefault="Deny" />
ويرايش كرده و مقدار overrideModeDefault آن‌را به Allow‌ تنظيم كرد:
<section name="requestFiltering" overrideModeDefault="Allow" />
مقدار پيش فرض maxRequestLength در IIS6 مساوي 4 مگابايت و مقدار پيش فرض maxAllowedContentLength در IIS7 مساوي 28.6MB‌ مي‌باشد. maxAllowedContentLength از نوع UINT32 است يعني حداكثر تا 4 گيگابايت را توسط آن مي‌توان مقدار دهي كرد. maxRequestLength از نوع Int32 است با حداكثر مقدار قابل تنظيم 2 گيگابايت.



۱۳۸۸/۰۹/۰۲

سيلورلايت 4 و پشتيباني رسمي از RTL


بالاخره پشتيباني رسمي از زبان‌هاي راست به چپ به سيلور لايت 4 كه اخيرا نسخه‌ي بتاي آن منتشر شده، اضافه گرديد. براي استفاده از آن نياز به VS2010 Beta2 به همراه ابزارهاي جديد آن و يا نسخه‌‌ي جديد Microsoft Expression Blend for .NET 4 Preview مي‌باشد.


تا پيش از اين، پروژه سورس بازي به نام SilverlightRTL يك سري كنترل را با پشتيباني از RTL ارائه داده بود كه اكنون تيم آن اعلام كرده است كه با آمدن سيلورلايت 4 ديگر اين پروژه را ادامه نخواهند داد.

۱۳۸۸/۰۸/۲۸

يافتن تداخلات Collations در SQL Server


اگر ديتابيس خود را در طي چند سال از يك نگارش به نگارشي ديگر يا از يك سرور به سروري ديگر منتقل كرده باشيد، به احتمال زياد به مشكلات Collations هم برخورده‌ايد. يكي از فيلدها Arabic_CI_AS است (بجا مانده از دوران قبل از SQL Server 2008) در يك جدول و در جدولي ديگر فيلدي تازه‌اي با Collation از نوع Persian_100_CI_AS تعريف شده است. Collations نحوه ذخيره سازي و مقايسه رشته‌ها را كنترل مي‌كنند. زمانيكه يك جدول جديد را در SQL Server ايجاد مي‌كنيم، اگر Collation فيلدها به صورت صريح ذكر نگردند، بر مبناي همان Collation پيش فرض ديتابيس تعريف خواهند شد.
بنابراين اگر پس از استفاده از SQL Server 2008 و تنظيم Collation پيش فرض ديتابيس به Persian_100_CI_AS ، به اين موارد دقت نكنيم، دير يا زود دچار مشكل خواهيم شد.
عمليات مرتب سازي با وجود تداخلات Collations مشكل ساز نمي‌شود (خطايي دريافت نمي‌كنيد)، اما ممكن است الزاما صحيح عمل نكند. مشكل از آنجايي آغاز مي‌شود كه قصد داشته باشيم داده‌ها را مقايسه كنيم يا join ايي بين اين دو جدول با فيلدهاي ناهمگون از لحاظ Collation ايجاد نمائيم. در اين حالت حتما خطاهاي تداخل Collation را دريافت كرده و كوئري‌هاي ما اجرا نخواهند شد.
Cannot resolve collation conflict for equal to operation

يك راه حل اين است كه در حين join به صورت صريح collation هر دو فيلد ذكر شده را به صورت يكسان ذكر كنيم كه بيشتر يك مرهم موقتي است تا راه حل اصولي. براي مثال:
SELECT ID
FROM ItemsTable
INNER JOIN AccountsTable
WHERE ItemsTable.Collation1Col COLLATE DATABASE_DEFAULT
= AccountsTable.Collation2Col COLLATE DATABASE_DEFAULT
راه ديگر اين است كه مشخص كنيم كه Collation كدام فيلدها در ديتابيس با Collation پيش فرض ديتابيس تطابق ندارند. سپس بر اساس اين ليست شروع به تغيير Collations نمائيم.
اسكريپت زير تمام فيلدهاي ناهمگون از لحاظ Collation ديتابيس جاري را براي شما ليست خواهد كرد:
DECLARE @defaultCollation NVARCHAR(1000)
SET @defaultCollation = CAST(
DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS NVARCHAR(1000)
)

SELECT C.Table_Name,
Column_Name,
Collation_Name,
@defaultCollation DefaultCollation
FROM Information_Schema.Columns C
INNER JOIN Information_Schema.Tables T
ON C.Table_Name = T.Table_Name
WHERE T.Table_Type = 'Base Table'
AND RTRIM(LTRIM(Collation_Name)) <> RTRIM(LTRIM(@defaultCollation))
AND COLUMNPROPERTY(OBJECT_ID(C.Table_Name), Column_Name, 'IsComputed') = 0
ORDER BY
C.Table_Name,
C.Column_Name
براي مثال جهت تغيير Collation فيلد Serial از جدول tblArchive از نوع nvarchar با طول 200 به Persian_100_CI_AS مي‌توان از دستور T-SQL زير استفاده كرد:
ALTER TABLE [tblArchive] ALTER COLUMN [Serial] nvarchar(200) COLLATE Persian_100_CI_AS not null

۱۳۸۸/۰۸/۲۷

SharePoint2010 و قابليت FileStream


اگر خاطرتان باشد يك مقاله سه قسمتي در مورد قابليت جديد FileStream مربوط به SQL Server 2008 چندي قبل در اين سايت منتشر شد (+ و + و +).
خبر خوش اين است كه اين قابليت تحت عنوان Remote Blob Storage يا RBS در شيرپوينت 2010 (كه نسخه‌ي بتاي آن يكي دو روزي است كه به مشتركين MSDN ارائه شده) قابل استفاده مي‌باشد و به اين صورت مي‌توان به سادگي از مزاياي اين فناوري جديد بهره‌مند شد.
مستندات رسمي فعال سازي اين قابليت در شيرپوينت 2010:


اين قابليت Remote Blob Storage در شيرپوينت 2007 هم قابل پياده سازي است اما پشتيباني رسمي نمي‌شود:


پ.ن.
ارزش اين چند سطري كه مطالعه فرموديد حدود يك ميليون و 200 هزار تومان مطابق قيمتي است كه از يكي از شركت‌هاي داخلي مدعي اختراع اين فناوري براي شيرپوينت 2007، دريافت شده است!

۱۳۸۸/۰۸/۲۶

JSLint.VS


JSLint.VS افزونه‌اي است رايگان براي VS.Net2005/2008 جهت بررسي ساده‌تر مشكلات دستوري در فايل‌هاي JavaScript يك پروژه.


اكنون بجاي اينكه در مرورگر به دنبال خطاهاي گزارش شده بگرديم، مي‌توان پيش از بررسي نهايي آن‌ها، در VS.Net‌ مشكلات ممكن را يافته و برطرف ساخت.
JSLint.VS به منوي كليك راست بر روي يك فايل js اضافه مي‌شود و يا در حالت انتخاب قطعه‌اي كد و سپس كليك راست و بررسي مشكلات موجود و يا در حالت يكپارچه با امكانات build پروژه قابل استفاده است (براي يكپارچه سازي با Build بايد به منوي Tools قسمت JSLint.VS options مراجعه كرد و سپس گزينه build را درصفحه ظاهر شده تيك زد).



پس از دريافت آن، محتويات پوشه bin آن‌را در مسير زير كپي نمائيد:
%My Documents%/Visual Studio 2008/Addins
Or
%My Documents%/Visual Studio 2005/Addins

۱۳۸۸/۰۸/۲۵

كتابخانه‌ي انواع و اقسام مدل‌هاي داده‌اي


سايت databaseanswers.org قسمتي را دارد تحت عنوان Data models كه طراحي ديتابيس بيش از 600 سيستم را جمع آوري كرده است.
از data model سيستم مديريت ارتباطات



تا data model يك باغ وحش





۱۳۸۸/۰۸/۲۴

NiftyDotNet!


NiftyDotNet يك كنترل ASP.Net 2.0 است كه امكان ساخت قطعاتي با گوشه‌هاي گرد را به سهولت ميسر مي‌سازد. اين كنترل در حقيقت محصور كننده‌ي مجموعه Nifty Corners Cube است.

صفحه‌ي اصلي در گوگل كد
يك سري مثال كاربردي
دريافت سورس، مثالها و فايل بايناري آن از رپيدشير

مثال:
گرد كردن گوشه‌هاي div ايي با id‌ مساوي box1 كه توسط خاصيت Selectors اين كنترل مشخص شده است (اگر class اين div براي مثال مساوي cls1 بود اين مقدار مي‌بايست مساوي div.cls1 قرار مي‌گرفت؛ شبيه به روش jQuery).
<%@ Register Assembly="NiftyDotNet" Namespace="NiftyDotNet" TagPrefix="cc1" %>

<div id="container">
<cc1:Nifty ID="Nifty1" runat="server" CornerSize="Big" Selectors="div#box1">
</cc1:Nifty>
<div id="box1" style="background: #e6e6e6; color: Black; width: 18em;">
<h1>
NiftyDotNet</h1>
<p>
Just drag & drop to round!</p>
</div>
</div>


۱۳۸۸/۰۸/۲۳

سه ابزار امنيتي جديد جهت توسعه دهندگان وب


مايكروسافت سه ابزار امنيتي رايگان جديد را جهت توسعه دهندگان وب ارائه داده است كه فعلا در مرحله آزمايش به سر مي‌برند و قرار است اين مجموعه به صورت جرئي از مجموعه power tools ويژوال استوديو 2010 ارائه شوند. اين سه ابزار به شرح زير هستند:

الف) CAT.NET 2.0 CTP
CAT.NET كاملا از صفر بازنويسي شده و از موتور جديدي كمك مي‌گيرد. نگارش CTP فعلي آن فقط از طريق خط فرمان قابل اجرا است.
دريافت

ب) WACA 1.0 CTP
نام اين ابزار مخفف Web Application Configuration Analyzer است كه جهت بررسي تنظيمات برنامه‌هاي وب شما، همچنين IIS و SQL Server بكار مي‌رود و نقايص امنيتي آن‌ها را گوشزد خواهد كرد.
دريافت

ج) WPL 1.0 CTP
نام اين ابزار مخفف Web Protection Library است. اين ابزار شبيه به يك فايروال جهت برنامه‌هاي وب شما در مقابل حملات XSS و SQL injection عمل مي‌كند و بدون نياز به تغيير كد (با كمك يك HTTP Module)، محافظت قابل توجهي را ارائه خواهد داد.
دريافت

۱۳۸۸/۰۸/۲۰

راهنماي مديريت ديتابيس‌هاي SharePoint


مايكروسافت اخيرا كتابچه‌اي را منتشر كرده است كه در آن نحوه‌ي نگهداري و بهبود كارآيي ديتابيس‌هاي اس كيوال سرور 2008 مخصوص شيرپوينت 2007 را توضيح داده است. حتي اگر سر و كار شما با شيرپوينت نيست اما با ديتابيس‌هاي حجيم و غول پيكر اس كيوال سرور 2008 سر و كار داريد، خواندن نكات اين مجموعه توصيه مي‌شود.

دريافت اين راهنما با فرمت pdf
دريافت اين راهنما با فرمت docx


سري آموزشي PRISM


PRISM يا Composite Application Guidance الگوهايي را براي توليد برنامه‌هاي WPF ويا Silverlight ماژولار با قابليت تست پذيري بالا ارائه مي‌دهند. شعار اين مجموعه built for change و built to last است كه به معناي تهيه سيستم‌هايي با قابليت تغيير بالا و همچنين سهولت نگهداري آن‌ها در دراز مدت مي‌باشد.
جناب Mike Taulty را احتمالا با ويديوهاي آموزش WCF به خاطر داريد. ايشان مجموعه جديدي را به نام Video Series on PRISM for Silverlight 3 تهيه كرده‌اند كه از لينك‌هاي زير قابل دريافت است:





۱۳۸۸/۰۸/۱۸

پيش ثبت نام براي دريافت SharePoint 2010 beta


اگر علاقمند باشيد كه نحوه دريافت SharePoint 2010 beta كه در اواخر ماه جاري عرضه خواهد شد، به اطلاع شما رسانده شود، در آدرس زير پيش ثبت نام نمائيد:




پردازش موازي در VS2010


دموي نسبتا مفصلي از توانايي‌هاي دات نت فريم ورك 4 و VS2010 را كه توسط تيم مربوطه در مورد پردازش موازي تهيه شده است، از آدرس زير مي‌توانيد دريافت نمائيد.





۱۳۸۸/۰۸/۱۵

امنيت در LINQ to SQL


سؤال: LINQ to SQL تا چه ميزان در برابر حملات تزريق SQL امن است؟
جواب كوتاه: بسيار زياد!

توضيحات:
string query = @"SELECT * FROM USER_PROFILE
WHERE LOGIN_ID = '"+loginId+@"' AND PASSWORD = '"+password+@"'";
گاهي از اوقات هر چقدر هم در مورد خطرات كوئري‌هايي از نوع فوق مقاله نوشته شود كافي نيست و باز هم شاهد اين نوع جمع زدن‌ها و نوشتن كوئري‌هايي به شدت آسيب پذير در حالت استفاده از ADO.Net كلاسيك هستيم. مثال فوق يك نمونه كلاسيك از نمايش آسيب پذيري در مورد تزريق اس كيوال است. يا نمونه‌ي بسيار متداول ديگري از اين دست كه با ورودي خطرناك مي‌تواند تا نمايش كليه اطلاعات تمامي جداول موجود هم پيش برود:
protected void btnSearch_Click(object sender, EventArgs e)
{
String cmd = @"SELECT [CustomerID], [CompanyName], [ContactName]
FROM [Customers] WHERE CompanyName ='" + txtCompanyName.Text
+ @"'";

SqlDataSource1.SelectCommand = cmd;

GridView1.Visible = true;
}
در اينجا فقط كافي است مهاجم با تزريق عبارت SQL مورد نظر خود، كوئري اوليه را كاملا غيرمعتبر كرده و از يك جدول ديگر در سيستم كوئري تهيه كند!
راه حلي كه براي مقابله با آن در دات نت ارائه شده نوشتن كوئري‌هاي پارامتري است و در اين حالت كار encoding اطلاعات ورودي به صورت خودكار توسط فريم ورك مورد استفاده انجام خواهد شد؛ همچنين براي مثال اس كيوال سرور، execution plan اين نوع كوئري‌هاي پارامتري را همانند رويه‌هاي ذخيره شده، كش كرده و در دفعات آتي فراخواني آن‌ها به شدت سريعتر عمل خواهد كرد. براي مثال:
SqlCommand cmd = new SqlCommand("SELECT UserID FROM Users WHERE UserName=@UserName AND Password=@Password");
cmd.Parameters.Add(new SqlParameter("@UserName", System.Data.SqlDbType.NVarChar, 255, UserName));
cmd.Parameters.Add(new SqlParameter("@Password", System.Data.SqlDbType.NVarChar, 255, Password));
dr = cmd.ExecuteReader();
if (dr.Read()) userId = dr.GetInt32(dr.GetOrdinal("UserID"));
زمانيكه از كوئري پارامتري استفاده شود، مقدار پارامتر، هيچگاه فرصت و قدرت اجرا پيدا نمي‌كند. در اين حالت صرفا به آن به عنوان يك مقدار معمولي نگاه خواهد شد و نه جزء قابل تغيير بدنه كوئري وارد شده كه در حالت جمع زدن رشته‌ها همانند اولين كوئري معرفي شده، تا حد انحراف كوئري به يك كوئري دلخواه مهاجم قابل تغيير است.

اما در مورد LINQ to SQL چطور؟
اين سيستم به صورت پيش فرض طوري طراحي شده است كه تمام كوئري‌هاي SQL نهايي حاصل از كوئري‌هاي LINQ نوشته شده توسط آن، پارامتري هستند. به عبارت ديگر اين سيستم به صورت پيش فرض براي افرادي كه داراي حداقل اطلاعات امنيتي هستند به شدت امنيت بالايي را به همراه خواهد آورد.
براي مثال كوئري LINQ زير را در نظر بگيريد:
var products = from p in db.products
where p.description.StartsWith(_txtSearch.Text)
select new
{
p.description,
p.price,
p.stock

};
اكنون فرض كنيد كاربر به دنبال كلمه sony باشد، آنچه كه بر روي اس كيوال سرور اجرا خواهد شد، دستور زير است (ترجمه نهايي كوئري فوق به زبان T-SQL) :
exec sp_executesql N'SELECT [t0].[description], [t0].[price], [t0].[stock]
FROM [dbo].[products] AS [t0]
WHERE [t0].[description] LIKE @p0',N'@p0 varchar(5)',@p0='sony%'
براي لاگ كردن اين عبارات SQL يا مي‌توان از SQL profiler استفاده نمود و يا خاصيت log زمينه مورد استفاده را بايد مقدار دهي كرد:
 db.Log = Console.Out;
و يا مي‌توان بر روي كوئري مورد نظر در VS.Net يك break point قرار داد و سپس از debug visualizer مخصوص آن استفاده نمود.

همانطور كه ملاحظه مي‌كنيد، كوئري نهايي توليد شده پارامتري است و در صورت ورود اطلاعات خطرناك در پارامتر p0 ، هيچ اتفاق خاصي نخواهد افتاد و صرفا ركوردي بازگشت داده نمي‌شود.

و يا همان مثال كلاسيك اعتبار سنجي كاربر را در نظر بگيريد:
public bool Validate(string loginId, string password)
{
DataClassesDataContext db = new DataClassesDataContext();

var validUsers = from user in db.USER_PROFILEs
where user.LOGIN_ID == loginId
&& user.PASSWORD == password
select user;

if (validUsers.Count() > 0) return true;
else return false;
}
كوئري نهايي T-SQL توليد شده توسط اين ORM از كوئري LINQ فوق به شكل زير است:
SELECT [t0].[LOGIN_ID], [t0].[PASSWORD]
FROM [dbo].[USER_PROFILE] AS [t0]
WHERE ([t0].[LOGIN_ID] = @p0) AND ([t0].[PASSWORD] = @p1)
و اين كوئري پارامتري نيز در برابر حملات تزريق اس كيوال امن است.

تذكر مهم هنگام استفاده از سيستم LINQ to SQL :

اگر با استفاده از LINQ to SQL مجددا به روش قديمي اجراي مستقيم كوئري‌هاي SQL خود همانند مثال زير روي بياوريد (اين امكان نيز وجود دارد)، نتيجه اين نوع كوئري‌هاي حاصل از جمع زدن رشته‌ها، پارامتري "نبوده" و مستعد به تزريق اس كيوال هستند:
string sql = "select * from Trade where DealMember='" + this.txtParams.Text + "'";
var trades = driveHax.ExecuteQuery<Trade>(sql);
در اينجا بايد در نظر داشت كه اگر شخصي مجددا بخواهد از اين نوع روش‌هاي كلاسيك استفاده كند شايد همان ADO.Net كلاسيك براي او كافي باشد و نيازي به تحميل سربار يك ORM را به سيستم نداشته باشد. در اين حالت برنامه از type safety كوئري‌هاي LINQ نيز محروم شده و يك لايه بررسي مقادير و پارامترها را توسط كامپايلر نيز از دست خواهد داد.

اما روش صحيحي نيز در مورد بكارگيري متد ExecuteQuery وجود دارد. استفاده از اين متد به شكل زير مشكل را حل خواهد كرد:
IEnumerable<Customer> results = db.ExecuteQuery<Customer>(
"SELECT contactname FROM customers WHERE city = {0}", "Tehran");
در اين حالت، پارامترهاي بكارگرفته شده (همان {0} ذكر شده در كوئري) به صورت خودكار به پارامترهاي T-SQL ترجمه خواهند شد و مشكل تزريق اس كيوال برطرف خواهد شد (به عبارت ديگر استفاده از +، علامت مستعد بودن به تزريق اس كيوال است و بر عكس).

Vote on iDevCenter

۱۳۸۸/۰۸/۱۳

مرجعي در مورد نگارش‌هاي مختلف SQL Server


آيا مي‌دانيد كه تا اين تاريخ پس از ارائه سرويس پك يك اس كيوال سرور 2008، دقيقا 5 به روز رساني ديگر نيز در مورد آن منتشر شده‌اند؟
آيا مي‌دانيد پس از ارائه سرويس پك سه مربوط به اس كيوال سرور 2005 ، دقيقا 10 مورد به روز رساني ديگر آن نيز منتشر گرديده‌اند؟
آيا مي‌دانيد پس از سرويس پك 4 اس كيوال سرور 2000 دقيقا چند مورد به روز رساني مرتبط با آن منتشر شده‌اند؟ (72 مورد!)
آيا مي‌دانيد دقيقا از چه نگارشي از SQL Server با كدام به روز رساني‌ها استفاده مي‌كنيد؟

پاسخ دقيق به تمام اين سؤالات را به صورت طبقه بندي شده و بسيار منظم، در وبلاگ زير مي‌توانيد مشاهده نمائيد:



۱۳۸۸/۰۸/۱۰

jQuery Ajax و نحوه صحيح ارسال مقادير به يك وب سرويس


در مورد كار با jQuery Ajax و نحوه فراخواني يك متد وب سرويس توسط آن، چند مطلب پيشتر ارائه شدند:
بررسي وجود نام كاربر با استفاده از jQuery Ajax در ASP.Net
و ...

تمام اين مقالات يك ايراد مهم دارند كه امروز با آن مواجه شدم و خلاصه آن به شرح زير است:
پارامتر data متد Ajax جي‌كوئري را به صورت زير در نظر بگيريد:
data: "{'username': '" + $('#<%= TextBox1.ClientID %>').val() + "'}",
اين روش شايد با بسياري از ورودي‌ها كار كند اما يك سري از كاراكترها زمانيكه با فرمت JSON ارسال مي‌شوند بايد اصطلاحا escape شوند كه ليست آن‌ها به صورت زير است:
\b  Backspace (ascii code 08)
\f Form feed (ascii code 0C)
\n New line
\r Carriage return
\t Tab
\v Vertical tab
' Apostrophe or single quote
" Double quote
\ Backslash caracter
براي حل اين مشكل مي‌توان از اسكريپت استاندارد json2.js كه در سايت json.org معرفي شده، استفاده كرد.

ابتدا ارجاعي از اين اسكريپت بايد به صفحه اضافه شود:
<script src="js/json2.js" type="text/javascript"></script>
سپس مقدار پارامتر data را بايد به شكل زير اصلاح كرد:
 var jsonText = JSON.stringify({ username: $('#<%= TextBox1.ClientID %>').val() });
...

data: jsonText,
متد stringify تمام ملاحظات لازم را در مورد escape كاراكترهاي ياد شده و بسياري از موارد ديگر به صورت خودكار اعمال مي‌كند. همچنين از اين لحاظ كه يك ساختار داده‌اي جاوا اسكريپتي را نيز مي‌تواند به معادل متني آن تبديل كند، بسيار جالب توجه است.
به عنوان مثالي ديگر، اگر متد وب سرويس ما دو پارامتر داشت، jsonText به شكل زير در خواهد آمد:
 var jsonText = JSON.stringify({ param1: val1, param2: val2 });
لازم به ذكر است كه پشتيباني از اين متد در نگارش‌هاي آخر اكثر مرورگرهاي امروزي در جهت سازگاري با آخرين استانداردهاي مصوب جاوا اسكريپت به صورت بومي وجود دارد (از IE8 به بعد و فايرفاكس 3 و يك به بعد)، اما از آنجائيكه كاربران ممكن است هنوز از نگارش‌هاي قديمي آن‌ها استفاده كنند، كمك گرفتن از فايل json2.js ضروري به نظر مي‌رسد.

Vote on iDevCenter