اشتراکها
یک نکتهی تکمیلی
اگر از Rider و یا ReSharper استفاده کنید، این نکتهی اهمیت ترتیب تعریف فیلدهای استاتیک را به صورت «Static member initializer refers to static member below or in other type part» نمایش میدهد:
لطفا در صورت امکان توضیح دهید در معماری توزیع شده چرا از کافکا برای Message broker استفاده کردید؟ و مثلا چرا RabbitMq رو انتخاب نکردید؟ با توجه به اینکه مرسوم است که میگویند در سیستم هایی که سرعت ارسال پیام و Real time بودن برای شما اهمیت داشته باشد rabbit انتخاب بهتری است.
در قسمت اول (اهمیت آشنایی با npm) در این مورد مقدمهای عنوان شد.
- این مورد بیشتر انتخاب شخصی است. مدیریت کنندههای بستهی زیادی وجود دارند و اشخاص میتوانند انتخاب کنند.
- bower خودش یکی از ابزارهای NodeJS است که توسط npm نصب میشود. بنابراین زمانیکه از bower استفاده میکنید، زیرساخت کار یکی است.
- این مورد بیشتر انتخاب شخصی است. مدیریت کنندههای بستهی زیادی وجود دارند و اشخاص میتوانند انتخاب کنند.
- bower خودش یکی از ابزارهای NodeJS است که توسط npm نصب میشود. بنابراین زمانیکه از bower استفاده میکنید، زیرساخت کار یکی است.
نظرات مطالب
اطلاع از بروز رسانی نرم افزار ساخته شده
Assembly Version برای مصرف کنندگان اسمبلی شما مهمه (و فقط در دنیای CLR دارای اهمیت هست). مثلا شخصی ارجاعی به اسمبلی نگارش خاصی داره. AssemblyFileVersion در قسمت خواص فایل در ویندوز قابل مشاهده است و بیشتر برای برنامههای ست آپ مفیده. اطلاعات بیشتر
سؤال شما مرتبط با موضوع نیست. یک فصل حدود 40 صفحهای در مورد WCF RIA Services در کتاب سیلورلایتی که منتشر شد وجود دارد. برای درک اهمیت آن باید فصلهای قبلی آنرا مطالعه کنید تا برسید به این فصل.
SL04.zip
SL04.zip
سلام
ممنون.
در این موارد کلان، مباحث مقیاس پذیری، load balancing ، mirroring ، clustering ، caching و امثال آن هم حائز اهمیت میشود که باز هم برنامههای وب و امکانات مهیای برای آنها در این زمینه حرف اول را میزنند.
ممنون.
در این موارد کلان، مباحث مقیاس پذیری، load balancing ، mirroring ، clustering ، caching و امثال آن هم حائز اهمیت میشود که باز هم برنامههای وب و امکانات مهیای برای آنها در این زمینه حرف اول را میزنند.
دو نوع رمزنگاری را میتوان توسط iTextSharp به PDF تولیدی و یا موجود، اعمال کرد:
الف) رمزنگاری با استفاده از کلمه عبور
ب) رمزنگاری توسط کلید عمومی
الف) رمزنگاری با استفاده از کلمه عبور
در اینجا امکان تنظیم read password و edit password به کمک متد SetEncryption شیء pdfWrite وجود دارد. همچنین میتوان مشخص کرد که مثلا آیا کاربر میتواند فایل PDF را چاپ کند یا خیر (PdfWriter.ALLOW_PRINTING).
ذکر read password اختیاری است؛ اما جهت اعمال permissions حتما نیاز است تا edit password ذکر گردد:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Text;
namespace EncryptPublicKey
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
var readPassword = Encoding.UTF8.GetBytes("123");//it can be null.
var editPassword = Encoding.UTF8.GetBytes("456");
int permissions = PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY;
pdfWriter.SetEncryption(readPassword, editPassword, permissions, PdfWriter.STRENGTH128BITS);
pdfDoc.Open();
pdfDoc.Add(new Phrase("tst 0"));
pdfDoc.NewPage();
pdfDoc.Add(new Phrase("tst 1"));
}
Process.Start("TestEnc.pdf");
}
}
}
اگر read password ذکر شود، کاربران برای مشاهده محتویات فایل نیاز خواهند داشت تا کلمهی عبور مرتبط را وارد نمایند:
این روش آنچنان امنیتی ندارد. هستند برنامههایی که این نوع فایلها را «آنی» به نمونهی غیر رمزنگاری شده تبدیل میکنند (حتی نیازی هم ندارند که از شما کلمهی عبوری را سؤال کنند). بنابراین اگر کاربران شما آنچنان حرفهای نیستند، این روش خوب است؛ در غیراینصورت از آن صرفنظر کنید.
ب) رمزنگاری توسط کلید عمومی
این روش نسبت به حالت الف بسیار پیشرفتهتر بوده و امنیت قابل توجهی هم دارد و «نیستند» برنامههایی که بتوانند این فایلها را بدون داشتن اطلاعات کافی، به سادگی رمزگشایی کنند.
برای شروع به کار با public key encryption نیاز است یک فایل PFX یا Personal Information Exchange داشته باشیم. یا میتوان این نوع فایلها را از CA's یا Certificate Authorities خرید، که بسیار هم نیکو یا اینکه میتوان فعلا برای آزمایش، نمونهی self signed اینها را هم تهیه کرد. مثلا با استفاده از این برنامه.
در ادامه نیاز خواهیم داشت تا اطلاعات این فایل PFX را جهت استفاده توسط iTextSharp استخراج کنیم. کلاسهای زیر اینکار را انجام میدهند و نهایتا کلیدهای عمومی و خصوصی ذخیره شده در فایل PFX را بازگشت خواهند داد:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
namespace EncryptPublicKey
{
/// <summary>
/// A Personal Information Exchange File Info
/// </summary>
public class PfxData
{
/// <summary>
/// Represents an X509 certificate
/// </summary>
public X509Certificate[] X509PrivateKeys { set; get; }
/// <summary>
/// Certificate's public key
/// </summary>
public ICipherParameters PublicKey { set; get; }
}
}
using System;
using System.IO;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
namespace EncryptPublicKey
{
/// <summary>
/// A Personal Information Exchange File Reader
/// </summary>
public class PfxReader
{
X509Certificate[] _chain;
AsymmetricKeyParameter _asymmetricKeyParameter;
/// <summary>
/// Reads A Personal Information Exchange File.
/// </summary>
/// <param name="pfxPath">Certificate file's path</param>
/// <param name="pfxPassword">Certificate file's password</param>
public PfxData ReadCertificate(string pfxPath, string pfxPassword)
{
using (var stream = new FileStream(pfxPath, FileMode.Open, FileAccess.Read))
{
var pkcs12Store = new Pkcs12Store(stream, pfxPassword.ToCharArray());
var alias = findThePublicKey(pkcs12Store);
_asymmetricKeyParameter = pkcs12Store.GetKey(alias).Key;
constructChain(pkcs12Store, alias);
return new PfxData { X509PrivateKeys = _chain, PublicKey = _asymmetricKeyParameter };
}
}
private void constructChain(Pkcs12Store pkcs12Store, string alias)
{
var certificateChains = pkcs12Store.GetCertificateChain(alias);
_chain = new X509Certificate[certificateChains.Length];
for (int k = 0; k < certificateChains.Length; ++k)
_chain[k] = certificateChains[k].Certificate;
}
private static string findThePublicKey(Pkcs12Store pkcs12Store)
{
string alias = string.Empty;
foreach (string entry in pkcs12Store.Aliases)
{
if (pkcs12Store.IsKeyEntry(entry) && pkcs12Store.GetKey(entry).Key.IsPrivate)
{
alias = entry;
break;
}
}
if (string.IsNullOrEmpty(alias))
throw new NullReferenceException("Provided certificate is invalid.");
return alias;
}
}
}
اکنون رمزنگاری فایل PDF تولیدی توسط کلید عمومی، به سادگی چند سطر کد زیر خواهد بود:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace EncryptPublicKey
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
var certs = new PfxReader().ReadCertificate(@"D:\path\cert.pfx", "123");
pdfWriter.SetEncryption(
certs: certs.X509PrivateKeys,
permissions: new int[] { PdfWriter.ALLOW_PRINTING, PdfWriter.ALLOW_COPY },
encryptionType: PdfWriter.ENCRYPTION_AES_128);
pdfDoc.Open();
pdfDoc.Add(new Phrase("tst 0"));
pdfDoc.NewPage();
pdfDoc.Add(new Phrase("tst 1"));
}
Process.Start("Test.pdf");
}
}
}
پیش از فراخوانی متد Open باید تنظیمات رمزنگاری مشخص شوند. در اینجا ابتدا فایل PFX خوانده شده و کلیدهای عمومی و خصوصی آن استخراج میشوند. سپس به متد SetEncryption جهت استفاده نهایی ارسال خواهند شد.
نحوه استفاده از این نوع فایلهای رمزنگاری شده:
اگر سعی در گشودن این فایل رمزنگاری شده نمائیم با خطای زیر مواجه خواهیم شد:
کاربران برای اینکه بتوانند این فایلهای PDF را بار کنند نیاز است تا فایل PFX شما را در سیستم خود نصب کنند. ویندوز فایلهای PFX را میشناسد و نصب آنها با دوبار کلیک بر روی فایل و چندبار کلیک بر روی دکمهی Next و وارد کردن کلمه عبور آن، به پایان میرسد.
سؤال: آیا میتوان فایلهای PDF موجود را هم به همین روش رمزنگاری کرد؟
بله. iTextSharp علاوه بر PdfWriter دارای PdfReader نیز میباشد:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace EncryptPublicKey
{
class Program
{
static void Main(string[] args)
{
PdfReader reader = new PdfReader("TestDec.pdf");
using (var stamper = new PdfStamper(reader, new FileStream("TestEnc.pdf", FileMode.Create)))
{
var certs = new PfxReader().ReadCertificate(@"D:\path\cert.pfx", "123");
stamper.SetEncryption(
certs: certs.X509PrivateKeys,
permissions: new int[] { PdfWriter.ALLOW_PRINTING, PdfWriter.ALLOW_COPY },
encryptionType: PdfWriter.ENCRYPTION_AES_128);
stamper.Close();
}
Process.Start("TestEnc.pdf");
}
}
}
سؤال: آیا میتوان نصب کلید عمومی را خودکار کرد؟
سورس برنامه SelfCert که معرفی شد، در دسترس است. این برنامه قابلیت انجام نصب خودکار مجوزها را دارد.
مطلبی را روز قبل نوشتم در مورد تعیین اعتبار یک کوئری. این مورد از آنجایی حائز اهمیت میشود که برای مثال تغییری در ساختار یکی از جداول حاصل شود. اکنون میخواهیم بررسی کنیم آیا سیستم از کار افتاده یا نه!؟
شما میتوانید نام یک فیلد را تغییر دهید (حتی اگر این فیلد در یک رویه ذخیره شده استفاده شده باشد) و هیچ خطایی هم نخواهید گرفت و این منشاء دردسرهای زیادی خواهد بود.
در حالت استفاده از SET NOEXEC ON ، کوئری مورد نظر فقط کامپایل میشود و همچنین از لحاظ نحوی بررسی خواهد شد، اما این کافی نیست.
مثال زیر را در نظر بگیرید:
Create PROCEDURE Test1
AS
SELECT * FROM tblPIDs1
این کوئری قابل اجرا است. دکمهی F5 را فشار دهید، بلافاصله رویه ذخیره شدهی Test1 برای شما ایجاد خواهد شد.
سپس کوئری زیر را اجرا کنید:
USE testdb
SET NOEXEC ON;
exec test1 ;
SET NOEXEC OFF;
Command(s) completed successfully
ایرادی هم وارد نیست چون فقط عملیات parsing و compile صورت گرفته و نه اجرای واقعی رویه ذخیره شده. اینجا از لحاظ دستوری مشکلی وجود ندارد.
در این نوع موارد میتوان از SET FMTONLY ON استفاده کرد. این مورد اجرای غیر واقعی یک کوئری را سبب میشود (تاثیری روی دیتابیس موجود نخواهد داشت، برای مثال اگر در رویه ذخیره شما عبارت insert وجود داشت، دیتایی insert نخواهد شد) و تنها متادیتای حاصل را بازگشت میدهد. مثلا نام ستونهای یک کوئری را و همچنین در این حین اگر خطایی رخ داده باشد، آنرا نیز ارائه خواهد داد.
USE testdb
SET FMTONLY ON;
exec test1 ;
SET FMTONLY OFF;
Msg 208, Level 16, State 1, Procedure test1, Line 3
Invalid object name 'tblPIDs1'.
USE testdb;
SET NOCOUNT ON;
DECLARE @name NVARCHAR(MAX),
@sql NVARCHAR(MAX),
@type CHAR(2), -- object type
@type_desc NVARCHAR(60), -- object type description
@params NVARCHAR(MAX) -- parameters
DECLARE @tblInvalid TABLE (
-- invalid objects
[type_desc] NVARCHAR(60),
[name] NVARCHAR(MAX),
[error_number] INT,
[error_message] NVARCHAR(MAX),
[type] CHAR(2)
);
DECLARE testSPs CURSOR FAST_FORWARD
FOR
SELECT [name] = OBJECT_NAME(SM.[object_id]),
[type] = SO.[type],
SO.[type_desc],
[params] = (
SELECT (
SELECT CONVERT(
XML,
(
SELECT STUFF(
(
SELECT ', ' + [name] +
'=NULL' AS
[text()]
FROM sys.parameters
WHERE [object_id] = SM.[object_id]
FOR XML PATH('')
),
1,
1,
''
)
)
)
FOR XML RAW,
TYPE
).value('/row[1]', 'varchar(max)')
)
FROM sys.sql_modules SM
JOIN sys.objects SO
ON SO.[object_id] = SM.[object_id]
WHERE SO.[is_ms_shipped] = 0
AND SO.[type] = 'P'
OPEN testSPs
FETCH NEXT FROM testSPs INTO @name, @type, @type_desc, @params
WHILE (@@FETCH_STATUS = 0)
BEGIN
BEGIN TRY
SET @sql = 'SET FMTONLY ON; exec ' + @name + ' ' + @params +
'; SET FMTONLY OFF;'
--PRINT @sql;
EXEC (@sql) ;
END TRY
BEGIN CATCH
PRINT @type_desc + ', ' + @name + ', Error: ' + CAST(ERROR_NUMBER() AS VARCHAR)
+ ', ' + ERROR_MESSAGE();
INSERT INTO @tblInvalid
SELECT @type_desc,
@name,
ERROR_NUMBER(),
ERROR_MESSAGE(),
@type
;
END CATCH
FETCH NEXT FROM testSPs INTO @name, @type, @type_desc, @params
END
CLOSE testSPs
DEALLOCATE testSPs
SELECT [type_desc],
[name],
[error_number],
[error_message]
FROM @tblInvalid
ORDER BY
CHARINDEX([type], ' U V PK UQ F TR FN TF P SQ '),
[name];
توضیحات:
این کوئری، در دیتابیس جاری که در قسمت use dbname مشخص میشود، تمامی رویههای ذخیره شده را به صورت خودکار پیدا میکند. سپس لیست آرگومانهای آنها را نیز یافته و عبارت exec مربوطه را تشکیل میدهد. سپس با استفاده از SET FMTONLY ON سعی در شبیه سازی اجرای تک تک رویههای ذخیره شده میکند. اگر خطایی در این بین رخ داد، آنها را در یک جدول موقتی ذخیره کرده و در آخر نتیجه را نمایش میدهد.
ارزش این کوئری زمانی مشخص میشود که تعداد زیادی رویه ذخیره شده داشته باشید اما نمیدانید کدامیک از آنها بر اساس آخرین تغییرات صورت گرفته، هنوز معتبر هستند یا نه. آیا به قول معروف، سیستم اومد پایین یا خیر!؟
نکته:
قسمتی که از XML استفاده شده جهت concatenating نتیجه حاصل از کوئری، مورد استفاده قرار گرفته و این روزها بحث رایجی است که در بسیاری از سایتها در مورد آن میتوان مطالب مفیدی را یافت. راه دیگر انجام آن استفاده از COALESCE میباشد.
مآخذ:
Check Validity of SQL Server Stored Procedures
Which of your Stored Procedures are no longer Valid
SET FMTONLY ON