PDA

View Full Version : سوال: روش مناسب جهت Login کلاینت در Datasnap چیست؟



hp1361
یک شنبه 01 اردیبهشت 1392, 15:26 عصر
با سلام

اگر بخواهیم بصورت دستی و با کد عملیات لاگین در سمت کلاینت رو انجام بدیم، چه روشی مناسب تر است؟


بطور معمول بعد از ساختن کلاینت با ویزارد کد زیر ساخته میشه


function TClientModule1.GetServerMethods1Client: TServerMethods1Client;
begin
if FServerMethods1Client = nil then
begin
SQLConnection1.Open;
FServerMethods1Client:= TServerMethods1Client.Create(SQLConnection1.DBXCon nection, FInstanceOwner);
end;
Result := FServerMethods1Client;
end;


حالا با کد زیر کانکت میشیم

ClientModule1.SQLConnection1.Open;


روش دوم:

function TClientModule1.Connect(aHost, aPort, aProtocol, aUsername, aPassword: string): Boolean;
begin
SQLConnection1.Close;
SQLConnection1.Params.Values['HostName'] := aHost;
SQLConnection1.Params.Values['Port'] := aPort;
SQLConnection1.Params.Values['CommunicationProtocol'] := aProtocol;
SQLConnection1.Params.Values['DSAuthenticationUser'] := aUsername;
SQLConnection1.Params.Values['DSAuthenticationPassword'] := aPassword;
try
SQLConnection1.Open;
FServerMethods1Client := TServerMethods1Client.Create(SQLConnection1.DBXCon nection, FInstanceOwner);
Result := True;
except
on e: Exception do
System.SysUtils.Exception.Create(e.Message);

on ExDBXError: TDBXError do
System.SysUtils.Exception.Create(ExDBXError.Messag e);
end;
end;


ممنون

BORHAN TEC
دوشنبه 02 اردیبهشت 1392, 00:01 صبح
سلام
کاملاً مشخصه که روش دوم بهتره.

hp1361
شنبه 07 اردیبهشت 1392, 13:03 عصر
سلام

من از روش دوم برای لاگ این استفاده کردم و بعد از لاگ این کردن با کد زیر Disconnect کردم


procedure TClientModule1.Disconnect;
begin
if FServerMethods1Client <> nil then
FreeAndNil(FServerMethods1Client);
SQLConnection1.Close;
end;


حالا جای دیگه وقتی دوباره Connect رو صدا میزنم مقدار ServerMethods1Client نول بر میگردونه و برنامه ارور Access میده!

کجای کار مشکل داره؟

ممنون

BORHAN TEC
شنبه 07 اردیبهشت 1392, 17:28 عصر
سلام
چرا از FreeAndNil استفاده کرده اید؟ اصلاً چه لزومی داره که FServerMethods1Client رو Free کنید؟ :گیج:

hp1361
شنبه 07 اردیبهشت 1392, 17:52 عصر
سلام

والا این پروژه مارو کچل کرد! از بس زیرو روش کردیم!

این کدهارو توی نت یافتم(دوستان از بس به سایت های خارجی ارجاع میدن و اونها هم توضیح نمیدن چیکار کردن ما هم مجبور به کپی پیست شدیم!)

منم شک کردم اما وقتیدر متد Disconnect این FreeAndNil رو حذف میکنم اونوقت ارور Canvas میداد!

الان دستی تغییر دادم ارور 10061 رو میده!

یه بزرگواری کنی به زبان شیرین فارسی قدم به قدم بگی فلوچارت مانند چه کارا باید بشه خیله خوب میشه:

البته اینم بگم من می خوام کاربر هم بتونه کانکشن باز داشته باشه(یعنی لاگین که کرد یکسره کانکشن بر قرار باشه تا وقتی که برنامه بسته بشه)
هم کانکشن صرفا در زمان درخواست توابع باز بشه و بعد بسته بشه!(همیشه انتخاب با مشتری است!)

ممنون

hp1361
شنبه 07 اردیبهشت 1392, 20:28 عصر
سلام

بیایید با هم تحلیل کنیم

داریم:


unit ClientModuleUnit1;

interface

uses
System.SysUtils, System.Classes, ClientClassesUnit1;

type
TClientModule1 = class(TDataModule)
SQLConnection1: TSQLConnection;
private
FInstanceOwner: Boolean;
FServerMethods1Client: TServerMethods1Client;
function GetServerMethods1Client: TServerMethods1Client;
{ Private declarations }
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property InstanceOwner: Boolean read FInstanceOwner write FInstanceOwner;
property ServerMethods1Client: TServerMethods1Client read GetServerMethods1Client write FServerMethods1Client;

end;

var
ClientModule1: TClientModule1;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

constructor TClientModule1.Create(AOwner: TComponent);
begin
inherited;
FInstanceOwner := True;
end;

destructor TClientModule1.Destroy;
begin
FServerMethods1Client.Free;
inherited;
end;

function TClientModule1.GetServerMethods1Client: TServerMethods1Client;
begin
if FServerMethods1Client = nil then
begin
SQLConnection1.Open;
FServerMethods1Client:= TServerMethods1Client.Create(SQLConnection1.DBXCon nection, FInstanceOwner);
end;
Result := FServerMethods1Client;
end;

end.


دیتا ماژول ما دوتا پروپرتی داره
property InstanceOwner: Boolean read FInstanceOwner write FInstanceOwner;
property ServerMethods1Client: TServerMethods1Client read GetServerMethods1Client write FServerMethods1Client;

که مقدار InstanceOwner در زمان ساخت دیتاماژول مقدار دهی میشه. حالا کارش چیه نمیدونم(باید راهنمای دلفی رو ببینم)
و ServerMethods1Client که همون یونیت Proxy ماست که توابع سرور درش پیاده سازی شده و با دسترسی به این میتونیم توابع سرور رو هم فراخوانی کنیم.

خوب بریم سر داستان اصلی:
وقتی من از توی برنامه ام مینویسم

ClientModule1.ServerMethods1Client.EchoString('Hel lo World');

چون دارم مقدار پروپرتی ServerMethods1Client از ClientModule1 رو میخونم لذا تابع GetServerMethods1Client فراخوانی میشه که بصورت زیره
if FServerMethods1Client = nil then
begin
SQLConnection1.Open;
FServerMethods1Client:= TServerMethods1Client.Create(SQLConnection1.DBXCon nection, FInstanceOwner);
end;
Result := FServerMethods1Client;

یعنی
1:کانکشن برقرار میشود
2:FServerMethods1Client مقدار دهی میشود
3:توابع درخواستی Proxy اجرا میشوند


سوال اول:نقش InstanceOwner چیه؟
سوال دوم:به چه طریقی کد رو تغییر بدیم که بازدن یک دکمه در فرم اصلی تابع Proxy فراخوانی بشه و بعدش با زدن دکمه دیگه کانکشن بسته بشه؟

ممنون

tomalaki
پنج شنبه 30 خرداد 1392, 11:34 صبح
دوستان ببخشید اگه حرفم خیلی مبتدی هست و شاید غلط باشه. اما به نظر من login کردن با متد authentication دیتا اسنپ امن نیست. چون اگه یوزرنیم و پسورد یکی از کلاینت ها لو رفت، یه نفر با داشتن یه Radstudio میتونه خرابکاری کنه. چون دیگه به راحتی میتونه به متدهای سرور دسترسی داشته باشه. حالا اونی که یوزرنیم و پسوردش لو رفته مهم نیست، مهم کاربرهای دیگه هست. به نظر من باید روش دیگر به کار گرفت.

hp1361
پنج شنبه 30 خرداد 1392, 15:40 عصر
سلام

چه مشکلی داره؟اگر توابعی که به کاربر میدیم خوب مدیریت شده باشه مشکلی نداره که!

مثلا اگر استثنا ها رو خوب مدیریت کنیم نمیتونه بفهمه که توابع با چه دیتابیس هایی در ارتباط هست

مثل این میمونه که ما توابعی رو از یک DLL به دیگران میدیم اما اونا نمیدونن که درون دی ال ال چه اتفاقاتی می افته!

اینطور نیست؟

tomalaki
جمعه 31 خرداد 1392, 12:54 عصر
چیزی که من برای برنامه خودم میخوام به کار ببرم این منطق رو داره ( که شاید هم اشتباه هست). وقتی کاربر یوزر و پسورد خودش رو زد، توی اون درخواست شناسه کاربر توی پایگاه داده هم باهاش میاد (واسه ارسال کوئری هایی که به اون کاربر مربوط هست مثلا 3). بعد یه تابع هست که پیام های مربوط به کاربر رو retrieve میکنه که به عنوان پارامتر، شناسه کاربر رو ارسال میکنه. حالا کافیه که کسی که به اون تابع دسترسی داره به طور شانسی بیاد به عنوان پارامتر، پارامتر یه کاربر دیگه بده (مثلا شناسه 4، چون معمولا این شناسه ها auto increment هستند). هیچی دیگه، خیلی بد میشه. البته بازم تاکید میکنم، من مبتدی هستم و شاید منطق برنامه نویسی مشکل داشته باشه.

hp1361
جمعه 31 خرداد 1392, 13:20 عصر
سلام

توی هر برنامه ای که شما فرض کنید، اگر نام کاربری یا رمز عبور کسی لو رفت، این اتفاق نباید در سیستم اختلال ایجاد کنه! بلکه صرفا برای اون کاربر مشکل پیش خواهد آمد!

در Datasnap هم ما صرفاً توابعی محدود رو در اختیار یک کاربر که هم Authenticate و هم Authorize(درصورت لزوم) شده باشه قرار میدیم.

یک برنامه تحت وب رو هم اگه در نظر بگیرید، ما داریم توابعی رو در اختیار کاربر قرار میدم با این تفاوت که محیط اجراش وب بروزره و نه یک App. حالا اگه نام کاربری و رمز عبور کسی لو بره مشکلاتی پیش میاد. این برنامه نویسه که باید مقادیرپاس داده شده و کلا مواردی که لازمه رو چک کنه!

چیز دیگه ای مد نظر شماست؟

tomalaki
شنبه 01 تیر 1392, 00:04 صبح
توی محیط وب خرابکار در حالت معمول نمیتونه به توابعی که نوشته شده دسترسی داشته باشه. چون به سرور دسترسی نداره و اگه به سرور دسترسی پیدا کرد رسما باید فاتحه امنیت اون سیستم رو خوند. اما توی دیتا اسنپ و با روش authentication تنها کافی هست که یوزر نیم و پسورد یکی لو بره، خرابکار با یه RadStudio میتونه به همه متدهایی که برای کاربر تعریف شده دسترسی پیدا کرد. این به نظر من درست نیست. مثلا من توی برنامه ناشیانه خودم، اومدم یه فرم تهیه کردم که کاربر نام کاربری و رمز عبور خودش رو وارد میکنه میفرسته برای سرور دیتااسنپ، سرور دیتا اسنپ روی پایگاه داده نگاه میکنه اگه کاربری با اون یوزر و پس وجود داشت، valid رو true میکنه (توی DSAuthenticationManager)و نتیجه اش که شناسه کاربر هست بر میگردونه. حالا یه متد دیگه نوشتم که اطلاعات کاربر برمیگردونه و به عنوان پارامتر شناسه کاربر میگیره. مثلا get_info(user_id). حالا خرابکار میتونه هر شناسه ای رو وارد کنه و اطلاعات دیگران هم به دست بیاره. این درست نیست.

امیدوارم منظورم رو رسونده باشم. البته شاید منطقم اشتباه باشه.

hp1361
شنبه 01 تیر 1392, 11:15 صبح
سلام

در مثال شما چه دلیلی داره تابعی باشه که با ID کاربر اطلاعات رو برگردونه؟میتونید اطلاعات رو صرفا با نام کاربری و رمز عبور کاربر برگردونید! حالا صرفاً اطلاعات همون کاربر که نام کاربریش لو رفته در اختیار برنامه و در نتیجه خرابکار قرار میگیره!

چون ما برنامه رو نوشتیم دلیل نمیشه هر اطلاعاتی رو بهش پاس بدیم. برنامه سمت کلاینته و صرفا اطلاعات ضروری باید بهش داده بشسه(کلا باید در نظر گرفت که برنامه دست یک خرابکار افتاده)

درسته؟

tomalaki
شنبه 01 تیر 1392, 16:41 عصر
راه حل شما کاملا درسته. صحیح میفرمایین.