اینجا داریم با داده های تستی کار میکنیم
اینجا توی تصویر بالایی چون db context داریم ، داریم با دیتا بیس کار میکنیم
نکته ای که هست اینه که در مورد 4 ام که پایینی هستش ما اومدیم و awite رو پاک کردیم و در آخرش هم اومدیم از result استفاده کردیم که همین کار باعث شده که تابع async تبدیل بشه به sync که این کار اشتباه است
اینجا ما داریم با استفاده از result اومدیم و تابع async رو تبدیل کردیم به sync
با استفاده از task run اومدیم و بلاک کد به صورت async اجرا میشه
خوب توی کد بالا ما از دیتابیس استفاده نکردیم و اومدیم با task run اون رو به صورت async در آرودیم
دقت داشته باشیم که برای async کردن یه تابع نیاز داریم که اون اکشنی که میخوایم از نوع اکشن های دیتابیسی باشه ، یعنی این که به طور مثال دیتابیس رو هم اضافه کرده باشیم و چون داریم با collection ها هم استفاده میکنیم باید linq رو هم اضافه کنیم تا بتونیم از تابع های to list async , … و دیگر async ها استفاده کنیم
خوب where , to list , first or defaul اینها ex method هستند که باید system.linq رو به کد اضافه کنیم تا بتونیم ازش استفاده کنیم چرا first or deafult async یا to list aysnc چرا نیست ؟ جواب = چون باید یه ex method اضافه کنیم که برای دیتابیسه ، که میشه sys . ef core هستش
حالا میرسیم به Get all
کد بالا برای استفاده از دیتا بیس هستش ولی کد پایین بدون دیتابیس هستش
مراحل درست کردن Api pure
توی configure
اینطوری مینویسیم
یه پوشه به اسم conteoller ایحاد میکنیم و با اسم جمع مدلمون یه کنترلر ازش میسازیم
نکته برای تعیین مسیر به جای api مثلا میتونیم اون کنترلرهایی که مرتبط با یک موضوعی هستند که اینجا به طور مثال api هستش رو بریزیم توی یه فولدر و بعد اسمش رو هم اینطوری بزاریم توی route
خوب دلیل این که از conteoller base استفاده کردیم اینه که این پروژه فقط api هستش و اینجا نمیخوایم View برگردونیم
در کنترلر از controller base اومدیم ارث بری کردیم که میشه پایه ترین کلاس کنترلر ها و داخل کنترلر به یک منبع داده نیاز داریم اینه که میتونه هر چیزی باشه و میتونیم به دو روش این مبنع داده رو وارد کنترلر کنیم یکیش اینه که داخلش بیایم و new اش کنیم که اینطوری محدود به استفاده از همون هستیم فقط و راه دوم DI هستش
خوب یه نکته ای که هست اینه که نوشتن اون api در ادرس اجباری نیستش ولی اگر ، پروژه بزرگ باشه میتونیم به جاش بنویسیم CMS و بقیه اش و …
برای این کار میایم و توی constuctor اون چیزی که میخوایم رو بهش میدیم ، نکته ای که هست اینه که اون چیزی که میخوایم معرفی کنیم باید interface باشه و باید در جایی تعیین کنیم که اگر جایی در برنامه میخواست چیزی رو درست کنه و new کنه که توی ورودیش یه interface هستش به جای اون اینترفیسه بیا و این یکی کلاس رو new کن و ازش استفاده کن ، برای همین میایم توی startup :
خوب نکته ای که هست اینه که این ها دو تا پارامتر میگیرند اولیس اینترفیسه و دومی اون کلاس هستش
تمام توابع رو به صورت async مینویسیم مورد بعدی action result بنویسیم برای این که نوع respose رو میخوایم برگردونیم نوع خروجی رو هم به صورت کامل بنویسیم
قسمت 8
در entity framework مدل های ما poco هستش یعنی لزومی نداره که از اینترفیس یا کلاسی inherit کنند ولی database context اینطوری نیست و باید از dbcontext ارث بری کنه
در ورودی controctor چیزی به نام otions داریم که با استفاده ازش میایم از دنیای بیرون یه سری اطلاعات رو واردش میکنیم مثل connection string
چون اسم مدلمون command هستش میایم با اسم جمع مدلمون رو میسازیم و اسمش رو میزاریم Commands
در ef classic اگر اسم مدل بود Command خودش به صورت اتوماتیک اسم مدل رو commands میزاشت ولی در EF Core هر چیزی اسم گذاری کنیم میشه همون
خوب حالا میخوایم به جای این که بیایم در کنترلر repo رو new کنیم بیایم با DI این کار رو انجام بدیم
برای این کار باید بیایم و به contructor اون رو inject کنیم و بعد ازش استفاده کنیم
برای استفاده ازش باید از transient استفاده کنیم که به ازای هر request یه شی درست بشه
مثلا اگر یه شخصی درخواست داد و بعد از دوباره درخواست داد دوتا شی جدا درست میشه
خوب توی دیتابیس یه سری امکانات خاص داریم
به طور مثال این addDbContext کاره همون transient رو داره انجام میده در قسمت بعدی داریم به صورت generic میایم و دیتابیس رو بهش میدیم
خوب بعد توی قسمت option میایم میگیم که میخوایم از sql server استفاده میکنیم
خوب اون configuration از کجا اومده :
خوب همون اول برنامه میخواد اجرا بشه میخواد startup رو اجرا کنه و بعد میبینه که در ورودیش IConfiguration هستش بعد میره به صورت اتوماتیک configuration رو میسازه
اون چیزهایی که ما خودمون میخوایم بسازیم رو میریم توی configuration service مینویسیم ولی موارد built in که برای خوده برنامه است توی startup انجام میشه
نکته ای که هست اینه که Configuration اینجا set نداره ولی در startup اومده set شده ! چجوری ؟
اینجا یه مورد خاص هستش
نکته constant , read only خوب constatnt برای کلاس هستش و Read only برای اشیا هستش ، مورد بعدی اینه که constant ها رو همون موقع که میسازیموشن باید بهشون مقدار اولیه بدیم ، read only هم همون موقع که ساخته میشه باید بهشون مقدار بدیم یا توی constructor
خوب به جای ورژن بالا اینطوری میتونیم بنویسیم :
جلسه 9
برای کامپایل کردن dotnet build استفاده میکنیم
نکته : up در مقابل down هستش
خوب برای حذف کردنش هم از remove استفاده میکنیم
جلسه 10: خوب زمانی پیش میاد که بخوایم برای view که داریم از یه سری model استفاده کنیم برای همین کار میایم توی پوشه ی view models و اون چیزی که میخوایم رو میسازیم به طور مثال اگر ما بخوایم register کردن کاربر رو چک کنیم ممکنه که بگید از user استفاده کنیم برای مدل ، ولی نمیشه چون در چک کردن کاربر ما یه سری فیلد داریم که توی جدول user نیست و ما باید برای این کا اون model که میخوایم برای این کار رو درست کنیم
توی فولدر resources میایم busisness logic رو میاریم قبلا اسمش BLL بوده اینجا ما میخوایم shared busisness رو بنویسیم یعنی ممکنه چند جا استفاده بشه
در پروژه هیچ چیزی نباید به صورت hard code باشه هر متن و عنوان یا موارد دیگه
توی VS code ما resourse ندارد
برای این که میخوایم توی کل پروژه استفاده کنیم میایم public اش میکنیم
نکته : این name ها تبدیل به property میشن اینجا اتفاقی که میوفته اینه که در پشت صحنه میره و یه کلاس درست میکنه و به ازای هر اسمی در name میاد و به پراپرتی میسازه
در نتیجه name ها محدودیت دارند مثلا اسم پراپرتی نمیشه space داشته باشه ولی در قسمت value محدودیتی نداره
ستون comment فقط برای توضیحات خودمون نوشته شده
خوب برای تغییر زبان اینجا کافیه که ستون value رو ترجمه کنیم اینطوری زبان سایت تغییر میکنه
خوب اینجا به صورت اتوماتیک وقتی که شرایطش انجام نشه به صورت دیفالت یه پیغام میده حالا ما میخوایم این پیام رو عوض کنیم
خوب برای این که پیغام به صورت dynamic باشه این کار رو میکنیم :
اینجا به حجای اون 0 میاد و اسم اون پراپرتی رو میزاره
اگر اون پراپرتیمون attribute dispaly رو داشته باشه به جای این که اسم اون پراپرتی رو بنویسه میاد پیام اون display رو مینویسه
خوب اینجا میخوایم به
خوب داریم میگیم تایپ ارور از نوع error massage هستش و از نوع resource هستش و در قسمت دوم required که داره key رو میدیم بهش
اینجا magical string داریم که همین باعث میشه که ممکنه به ارور بخوریم
خوب smart resourse رو برای رفع این مشکل استفاده میکنیم حالا یه قابلیتی داریم به اسم name of
وقتی که میرسه به { } میره میبینه و چک میکنه که dispaly داره یا نه ، اگر نداشته باشه عینا اسم propery رو میزاره ولی اگر داشته باشه میره دوباره از روی resourses دوباره میخونه و بعد اون پیغام رو میسازه
قسمت 11
خوب culture در حال حاضر 2 حرفی مثلا fr en fa ,…
و 5 حرفیه fa-IR , en-UK
میرسیم به resourse :
اون آبی ها میشه slave
معمولا اینطوریه که master زبانش انگلیسی باشه و دومی فارسی برای این که دکمه ها رو فارسی کنیم
خوب اگر بخوایم button ها رو دو زبانه کنیم به جای این که new کنیم باید بیایم همونی که هست رو کپی کنیم
خوب resourses باید از نوع dot net standard باشه
اگر culter فارسی باشه اول میره توی همون فایل فارسی اگر پیدا کرد برمیداره اگر نه میره از روی master میخونه
نکته : وقتی که از جای دیگه فایل رو میگیریم میخوایم بزاریم توی پروژه نباید designer اش رو کپی کنیم
فقط کافیه که بریم resx رو کپی کنیم و بعد توی Resourse توی visusal studio بیایم و paste کنیم
دو تا layout هم درست میکنیم و براساس culture تغییرش میدیم
جلسه 12
یه فولدر میسازیم به اسم infrastructure و میایم کلاس های reusable رو توش مینویسیم
این کلاس ها همه جای پروژه میتونن استفاده بشن و میتونیم بیایم و در هرجای پروژه که میخوایم customize اش کنیم
خوب name space که داریم توی پروژه میشه namespace خوده پروژه بعد دات و بعد اسم پروژه
پوشه های models , view models و infostructure
میشه name space خوده پروژه دات اسم پوشه
اسم name space رو خوده اون پوشه میزاریم چون که وقتی که بخوایم مثلا پروژه حسابداری داشته باشیم به اسم accounting اینجا میشه accountg . infostructure
در این حالت اگر بخوایم از کلاس های infostructer در حاهای دیگه هم استفاده کنیم دیگه لازم نیست که namespace اش رو عوض کنیم
خوب اولین atrribute رو گذاشتیم برای این که اگر route رو تعیین نکردیم بهمون ارور بده و بعدی اومدیم route رو تعیین کردیم و سومی برای اینه که تعیین کنیم که json ارتباط داره
بعضی از کنترلر ها با دیتابیس کار میکنند یه سری هم نه
این جا مورد استثنا داره میگه که اگر ما پراپرتی رو تعریف کنیم که فقط get داشته باشه میتونیم توی constructor استثنا بهش مقدار بدیم
قسمت 12 تایم 16
خوب database context میره داخل unit of work و این که unit of work معادل database context هستش
خوب DI :
خوب در مباحث دیتابیسی باید از transient استفاده کنیم یعنی به ازای هر کاربر و هر req که ارسال میشه یه instance ازش ساخته بشه اینجا این خط به این معنی هست که هر جایی که در ورودیش از اینترفیس IUnitOfwork استفاده شده بیاد و یه نمونه از Unit of work ساخته بشه و inject بشه
حالا اینجا داره میگه که خوده unit of work یه سری پارامتر های ورودی داره که اینطوری میایم بهش مقدار دهی میکنیم
خوب توی اسم ها view model ها شبیه به همون dto ها هستند چون همون کار رو دارن میکنن
خوب برای ساختنش View model مینویسیم آخرش
اینجا به طور مثال اون قسمت هایی که توسط user داره پر میشه ، اون قسمتی هایی هم که توسط سرور باید پر بشه هم توسط سرور پر میشه و در نهایت کل این اطلاعات return میشه
خودمون یه کلاس برای برگردوندن نتایج ساختیم :
خوب اینجا جای models.application میتونیم از resultWithData و بعد models.application استفاده کنیم
قسمت 13
اول on action executing و بعد action و بعد on action executed میشد
خوب middleware ها قبل از ورود به action اتفاق میوفتد یعنی بعد از آخرین middleware میره وارد action میشه و بعد همون مسیر رو برمیگرده
در قسمت بالا ما یه middleware داریم که گفته هر request که به آدرس / اومد بهش پیام hello word رو بفرستیم
هر چیزی غیر از آدرس / بنویسیم کار نمیکند
خوب این کد بالا داره این رو میگه که هر req ای با هر verb به هر آدرسی زده شد بیا و hello world رو برگردون
خوب middleware ها اگر run باشند یه کاری رو انجام میدن و تمام میشه و سراغ middleware بعدی نمیره
خوب حالا مدل بعدی :
خوب اینجا داره میگه که بعد از این که middleware اولی انجام شد بره بعدی که همون next هستش در نسخه های قدیمی از next invoke استفاده میکنیم
نکته ای که هست اینه که middleware بعدی میشه app run و میره داخلش کار رو انجام میده و بعد هم تمام میشه و این قسمتش خیلی مهمه چون برمیگرده میره سراغ دستورات بعدی next که در قسمت بالایی نوشتیم
اینجا دستوری نوشته نشده ولی اگر نوشته شده بود زیره await next میشد
توی این حالت هم ما hello word 1 , 2 رو میبینیم
وقتی که arrow function بیشتر از یه مورد ورودی داره باید از پرانتز استفاده کنیم در غیر این صورت نمیخواد
خوب نتیجه به این شکل میشه :
خوب یه middleware داریم به اسم map که داریم اینجا ازش استفاده میکنیم به این صورت که اگر /test رو بزنیم میره و greeting رو اجرا میکنه
حالا اینجا حالتی که پیش میاد اینه که وقتی که ما /test رو نزدیم میره hello world رو اجرا میکنه ، ولی وقتی که /test رو میزنیم میره greeting رو اجرا میکنه و دیگه app . run رو اجرا نمیکنه
حالا اگر بخوایم app run هم بعدش اجرا بشه باید next رو توی greeting مینویشتیم
خوب اینجا فرض کنید که توی فولدر wwwroot اومدیم و یه فایل index.html گذاشتیم
**
حالا میخوایم بهش دسترسی پیدا کنیم ولی همچنان داره بهمون hello world نشون میده
خوب این middleware میاد نگاه میکنه ببینه که فایلی با اون اسمی که درخواست شده رو داریم یا نه ، اگر وجود داشت فایل رو میده ، اگر وجود نداشت میره بعدی
دقت باید داشته باشیم که ترتیب این middleware ها به چه صورت است و این که وقتی که run داشته باشیم یعنی انجام میشه و تمام ولی use ادامه داره
وقتی که break point میزاریم برای تست middleware با این که یه بار req زدیم ولی دو بار واردش میشه ، علتش اینه که مثلا وقتی که یه صفحه html رو درخواست میکنیم ، این میاد و fav icon رو هم باهاش میفرسته
برای همین بهتره که root پروژه fav icon رو داشته باشیم
قسمت 14
کلاس که قراره middleware باشه نباید از کلاس دیگه inherit شده باشه و نه از اینترفیسی
نکته اش اینه که باید constructor ای بنویسیم که ورودیش از جنس request delegate باشه
مرحله ی بعد نوشتن تابع invoke هستش که باید async باشه و چون خروجی نداره فقط میزنیم task
اگر void هستش خروجی :
خوب حالا چطوری میتونیم به کدمون بگیم که از این middleware استفاده کن از use middleware استفاده میکنیم
خوب خودمون میخوایم middleware static رو درست کنیم :
خوب یه نکته ای که داره اینه که ما اومدیم تعریف کردیم که اگر آدرس خالی بود برو به middleware بعد برای همین next رو نوشتیم و بعدش اومدیم return رو زدیم چون اگر برگشت هم کاری نداریم ، برای همین return اش کردیم
خوب اینجا داریم میگیم که بعد از / برو بردار هر چی بود رو
و css/site.css رو برمیداره میریزه توی path
توی mvc کلاسیک داریم sever . map pad رو داشتیم ولی توی core دیگه نداریمش
چون نیاز داریم به آدرس فیزیکی باید از host envitoment content root path استفاده کنیم
خوب حالا اگر خواستیم با این ها یه آدرس کامل بسازیم :
خوب برای همین از combine استفاده میکنیم و اون میاد این داستان این / ها رو در درست کردن ادرس حل میکنه
بیایم یه extention method بنویسیم برای استفاده از middleware ها
خوب حالا برای این که extestion کنیم باید چند تا کار انجام بدیم : اول این که static اش کنیم بعد public اش میکنیم قبل از اولین پارامتر ورودی این رو مینویسیم - اسم اون کلاسی که میخوایم بهش extent کنیم
اون هایی که کنار مکعبشون فلش داره extention method هستند و به صورت built in نبود اند و خوده microsoft اومده در جای دیگه ای بهشون اضافه کرده
آخر این قسمت راجه به middleware excption handling صحبت میکنه
قسمت 15
موضوع cors :
به خاطر مباحث security اتفاقی که میوفته اینه که اگر req از سمت سایتی به غیر از y.com به سمت x.com بره سرور اون رو جواب نمیده ، حتی میتونیم تعیین کنیم که فقط get ها رو جواب بده
خوب توی این حالت که هم بک اند داریم و هم فرانت اند باید بزنیم که چند تا پروژه با هم روی حالت run قرار بگیرند
خوب توی تنظیمات برای cors ما میایم و قسمت register , login رو برای همه باز میزاریم ولی بقیه ی قسمت ها که کارهای مربوط به admin هست رو میبندیم و میگیم که فقط از یه ip و با یه سری تنظیمات خاص میتونه بهش دسترسی پیدا کنه
خوب حالا مثلا برای این که بخوایم cors توی کنترلر که مرتبط با login , register فقط عمل کنه به صورت attribute میایم بالاش مینویسیم
قسمت 16 مشکلی که identity داره اینه که باید user رو بر اساس استاندارد microsft بسازیم ، آقای تصدیقی یه dtx security داره که باهاش میشه سطوح دسترسی رو بعد از این که سایت رو اوردیم بالا روش انجام بدیم
یعنی قابلیت authorize و role دادن به یوز ها
خوب میخوایم بعد از این که سایت رو آپلود کردیم ، حالا میخوایم یه اکشنی رو جلوش رو بگیریم و بگیم که فقط اون هایی که لاگین کردن فقط بهش دسترسی دارن و یا بلعکس و …
توی library microst همش به شکل هارد کد هستش ولی کامپوننت ما قابلیت کاستومایز شدن داره
توی ورژن های قدیمی session داشتیم که این ها یک سری اعداد صحیح بودن که sequensial بودن اولین نفر که وارد میشد بهش یه آی دی میداد و بعد میومد توی ram سرور ذخیره اش میکرد و به کلاینت هم میفرستادش مثلا میشد 17 بعد اون کلاینت هر درخواستی که میفرستاد میگفت که من 17 هستم و بعد سرور بهش سرویس رو میداد و این seeion id توی cookie ها ذخیره میشد و کافی بود که طرف بره و اون رو از 17 به 18 مثلا تغییر بده اینطوری میشد یه نفر دیگه
توی web form این ها تبدیل شدن به guid که یه سری اعداد رندوم هستن
بعدش ماکروسافت اومد هم Seeion و هم authorization رو اورد که در دل هم بودن یعنی دو تا id داشت
یعنی اگر seeion id داشت یعنی لاگین کرده و اگر seeion id نداشت یعنی لاگین نکرده و بعد id یکی دیگه
توی سایت های قدیمی هم بود اونجا که اسم ما رو میزد ولی به چیزی دسترسی نداشتیم و یا به یه چیزا دسترسی داشتیم ولی اسممون نبود برای این که timeout اشون متفاوت بودش
در این شرایط باید logut میکردم و بعد login میکردیم که این دو تا id با هم sync میشد
بعدش اومد idennity رو با authrization , autorazation رو اورمد
خوب فکر کنید که توی یه سازمانی 100 تا پروژه هست و اگر یک پرسنل توی 100 تا این ها باید لاگین میکرد و یکی بهش دسترسی میداد ولی این کاری که ما میخوایم بکنیم یه تفاوتی داره
حالا اگر ما idenity server داشته باشیم این قضیه فرق میکنه و اون طرف وقتی که وارد میشه همه دسترسی هاش اوکی میشه یعنی دسترسی ها و نقش ها همه پرسنل در یک سرور باشه و بیاد این رو انجام بده برای تمام سامانه هایی که دارن
اون شخص میاد لاگین میکنه و بعد یه token میگیره
و بعد اون شخص با اون توکن همه جا میره ، یا دسترسی هاش توی همون توکن هستش یا میره یه جایی چک میشه
مشکلی که داشتیم با session این بود که میومد اون id رو توی ram قرار میداد و مشکل این جا پیش میومد این بود که وقتی چند تا سرور میزاستیم و حالا اینجا ممکن بود اون شخصی که درخواست میده id اش توی این سرور نباشه
ما این کار رو میکردیم برای این که بتونیم load balance انجام بدیم و ممکنه ما توی یه سرور دیگه login کنیم و بعد درخواست بعدی رو به یه سرور دیگه میفرستادیم
اینجوری seeion in memory داشتیم و بعد برای حل این مشکل رو میبردیم همه رو توی database حالا مشکلی که پیش میومد این بود که حالا اینجا این سرور میشد bottle neck و مشکل داشتیم و مشکل بعدی اینه که توی Ram خیلی سریع تر ما میتونیم اطلاعات رو بخونیم تا بریم توی دیتابیس
خوب اول توی node اومد بعدش توی جاهای دیگه jwt میشه جوت این میاد یه json درست میکنه و میتونیم توش هر مدل پراپرتی رو قرار بدیم role , claim , … و بعد میاد این رو signed میکنه
وقتی که ما hash میکنیم یه اطلاعاتی رو مطاقا نمیتونیم به اصلش اون رو برگردونیم و این یعنی ما اینجا encription , decription نداریم
نکته ی بعدی signd میشه یعنی ecript نمیکنه خوب همه فکر میکنن که jwt یه چیزه enript شده ولی اینطوری نیست همون string که به اسم توکن میگیریم رو میتونیم توی سایت jwt بنویسیم و بهمون بگه اطلاعات توش چیه همه ی اطلاعات هستش
اون string که ما میبنیم یه مفهمومی داره به اسم base 64 و اون توکن میتونه بر اساس base 64 بیاد و برسیم به همون json ولی داستانی که داره اینه که این stirg میاد و Signed میشه و زیرش امضا میشه
اگر امضای الکترونیکی بر مبنای 50 ملیون باشه میایم چک میکنیم که ببینیم این امضا signed شده هم درسته و باهاش میخونه یا خیر
اگر این درست نبود پس یعنی داده دستکاری شده
اون چیزی که سمت سرور درست میشه اون بر مبنای enription symetric or asymetric اون رو میاد signed میکنه و در ادامه اش میزاره
هیچوقت اطلاعات محرمانه رو در jwt نزارید مثلا password نباید توی jwt باشه
درخواست میدیم و اون توکن میره توی سروری که خودش این رو ساخته و بعد میاد چک میکنه که این دیتا با اون توکن ، امضا اش میخونه یا خیر
خوب اول میاد یوزر و پسورد رو چک میکنه اگر اوکی بود میاد و ی توکن بهش میده
تمامی اطلاعات هویتی کاربر در jwt هستش ولی چون signed شده است کلید این که بخوایم signed کنیم این اطلاعات رو فقط توی سرور هستش و نگهداری میشه
حتی اگر توکن هم داشته باشیم مثلا role رو از یوزر تبدیلش کنیم به admin و بفرستیم سمت سرور ، سرور میفهمه که این اطلاعات با هم نمیخونه
اون هایی که داخلش هست ، یعنی بالایی داره از پایینیه استفاده میکنه
یه سری nuget ها به یه سری دیگه نیاز دارن برای اجرا شدن
برای sign کردن یه کلید نیاز داریم
اینجا خیلی جالبه ، به جای این که بیایم و یه dto یا view model درست کنه که این جا user رو بدون passsword ارسال کنیم ، اومدیم از serilization json ignore استفاده کردیم ، این یعنی این که وقتی که این کلاس دیتاش میخواد تببدلیل به json بشه ، این رو ignore میکنه و اصلا serilization روش انجام نمیده
اگر این کار و نکنیم باید یه کلاس دیگه درست کنیم به اسم user dto و بعد بیایم با auto mapper تمام فیلد هایی user رو به user dto مپ ککنیم ولی در پروژه های بزرگ این اشتباهه
قسمت 17
خوب
هر attribute که مینویسیم باید از system . attribute ارث بری کرده باشه هر attributr که مینویسیم باید آخر اسمش به attributr منتهی بشه
ولی توی نوشتنش اینطوری مینویسیم :
خوب اینجا چیزی که داره میگه اینه که این attr رو میشه هم برای class استفاده کرد و هم برای متد
اگر ما بالای یه کلاس بیایم Attr بزاریم برای تمامی قسمت هایی که توی اون کلاس هست اعمال میشه
هدف ما اینه که بیایم یه کاری کنیم که بالای هر action اومدیم این authorize رو نوشتیم باید طرف برای دسترسی لاگین کرده باشه
خوب برای این که به این قضیه برسیم باید از یه اینترفیسی هم استفاده کنیم که اسمش IAuthorized fileter باید استفاده کنیم
خوب بعدش اومدیم متد این انترفیس رو پیاده سازی کردیم :
خوب ورودی میاد و context میگیره و این context یعنی هر یوزری که میاد توی سایت این رو داره و یه سری اطلاعات مربوط به خودش داخل این هست
زمانی که طرف login کرده و بعد درخواست یه Action رو میده که attr که authroize دداره رو میده بعدش ما میایم توکنی که این یوزر باهاش لاگین کرده رو میگیریم ازش و برای backend ارسالش میکنیم
در middleware میایم اون توکن رو شناسایی میکنیم که سالمه و همه چیزش اوکیه ، اگر اوکی بود میریم شی اون user رو از دیتابیس میخونیم و بعدش میایم به مجموعه اطلاعاتی که توی http context هستش این user رو هم اضافه میکنیم
بعدش میره توی فیلتر و بعد میره توی action و …
توی این عکس بالا هم گفته که بره اون درخواستی که از سمت کلاینت میاد رو بره چک کنه ببینه که پارامتری به اسم uuser توش داره یا نه و اگر وجود داره بیاد cast اش کنه به model user
این جوری هم میشه cast کرد ولی احمقانه است چون که اگر به جای user مثلا country اگر توی اون شی ما بود - این باعث ارور در پروژه میشد
خوب بعدش گفتیم که اگر رفتیم چک کردیم و دیدیم که user برابر با null بود باید بهش پیام unathorized رو بدیم
خوب میایم اینطوری میسازیم :
توی mvc classic تنظیمات ما یه xml بود به اسم web config که توی نسخه ی جدید شده json و فرقشون اینه web config نوعش flat بود ولی توی json میتونیم درختی و nested پارامتر ها و تنظمیات رو بنویسیم
اکر این ساختار رو براش کلاس بسازیم میتونیم تعریف کنیم که از app setting بخونه و بعد مپ میکنه توی اون شی و دیگه لازم نیست که دونه دونه بخونیم و بعد ازش استفاده کینم
و اینجا یه چیزی داریم به اسم secret key و یه چیزی داریم به اسم token expires in min و باید با همین املا و کلمه این دو تا نوشته شود و برای همین هم اومدیم توی main به همین اسم این ها رو تعریف کردیم
بعدش یه پوشه میسازیم به اسم view models و بعد یه پوشه درست میکنیم ب اسم users
میخوایم برای یه Action به اسم login بیایم و یه view model درست کنیم خوب این action login داخل کدوم controller قرار داره ؟ میگیم کنترلر users اسم اون Action که میخوایم براش view model بنویسیم چیه ؟ login خوده login یه ورودی داره یه خروجی ، ورودی میشه Req و خروجی میشه Res و به کلمه ی View model هم باید ختم بشه
اینجا تعییرن کردیم کخه view model مون فقط user name و pass رو داشته باشه و براش required هم گذاشتیم
خوب حالا میخوایم توی Res بعد از این که کلاینت لاگین کرد چه اطلاعاتی رو بفرستیم براش
حالا کلاینت میتونه یه اپلیکشن blazor باشه یا اپ موبایل یا …
این ها رو میفرتسم و این که اون token همونیه که با jwt میخوایم بسازیمش
خوب ما این جا constructor نوشتیم که زمانی که user و token رو بهش میدی ، خودش بره اون پراپرتی ها رو مفدار دهی بکنه
و اگر اون یوزری که این درخواست رو میفرسته null باشه باید بهش خطا بدیم که شما login نکردی
اگر یه کلاسی داریم که یه سری از fild هاش reuqired هستش به جای Defualt constructor بیایم یه controctor براش بنویسیم با اون وردی هایی که اجباری هستش
حالا میخوایم service ها رو بنویسیم که معمولا business توش هستش
ما میتونیم یه کلاس درست کنیم و همه رو با هم inject کنیم ولی بهترش اینه که بیایم اول یه interface درست کنیم و بعد بیایم کلاس رو بسازیم و بعد توی di اعلام میکنیم که ورودی یه کلاسی اگر این interface بود بیا و این کلاس رو بساز و inject کن بهش
اینجا میخوایم id یوزر رو بدیم و خودش رو تحویل بگیریم میخوایم یه تابعی داشته باشیم به اسم get all که فهرست همه ی user ها رو بگیریم
خوب ما توی user service میخوایم از یه سری از اطلاعات توی App setting استفاده کینم برای همین اومدیم از Ioption استفاده کردیم و توی constructor اوردیمیش
خوب اینجا امدیم ب صورت تستی یه سری دیتا رو ساختیم ، اینجا گفتیم که اگر اون user برابر با null بود بیاد این آبجکت رو بسازه و اون رو برگردونه
خوب اینجا اگر میخواستیم از database استفاده کنیم باید از Database context استفاده میکردیم ، ولی اینجا اومدیم از model. user استفاده کردیم که در مرحله قبل اومدیم seed اش کردیم
خوب میرسیم به login
خوب اگر این قسمت رو رد کنه باید بیایم چک کنیم ببینیم که user name , pass درست ارسال شده یا خیر
خوب برای همین میایم میگیم ک بیا و برگرد و usr که شبیه به این user هستش رو بهمون بده اومدیم to lower اش هم کردیم و هر دو تاشون رو to lower کردیم
خوب حالا اگر user رو پیدا نکرد
حالا اگر پیداش کرد :
اینجا میایم و چک میکنیم pass رو با اونی که توی دیتابیس هستش و اینجا ignore cse رو گذاشتیم fasle که این یعنی این که بزرگ و کوجیک تاثیر داره
خوب اینحا وظیفه اش اینه که بیاد و یه توکن درست کنه و گفتیم که در ورودی بیاد user رو بگیر و کلید رو و …
خوب از main setting که توش secrt key داشتیم اومدیم اینجا استفاده کردیم
برای Sign کردن میریم و اون sercet key رو برمیداریم و میایم تبدیلش میکنیم به آرایه ای از بایت ها
چون برای Encription ما نیاز داریم که اون کلید به صورت byte باشه
بعد میایم بهش اون کلیده رو میدیم و ازش یه symetric key میگیریم
و بعد الگوریتیم که میخوایم باهاش singed کینیم رو تعیین میککینم :
و اینجا هم نوشته که singuture هستش
بعدش اومیدم اینطوری
اومیدیم گفتیم که میخوایم اطلاعات رو sign کنیم و بعد کلید و بعد هم الگوریتیم رو بهش میدیم و خودش درستش میکنه
خوب حالا مخوایم تعیین کنیم که داخل خوده توکن چه چیزهایی قراره باشه
خوب میتونه توش claim باشه ، که این ها میتونه با شخصیت باشه مثل مثلا اجازه ی دسترسی به ثبت فلان سند یا میتونه فقط اطلاعات کاربر باشه مثلا اسم و فامیل و …
خوب توی اون دو خط پایین کامنت ها ما داریم از type of استفاده میکنیم که اینطوری ما strongly type هستیم این با اون بالایی فرقی نداره ، فرقش در type safty شون هستش
میتونیم خودمون کلید تعریف کنیم ولی یه سری کلید هم built in توش هست که میتونیم ازش استفاده کینم
مثلا name
خوب
خوب اینه ها هم تشرفاتی هستند
میخوایم اعلام کنیم که کسی که این توکن رو خلق کرده یا همون issuer میشه مثلا سرور فلان توی دامین فلان درست کرده ،
خوب یه چیزه دیگه هم هست که میتونه اینجا کاربردی باشه مثلا وقتی که میدیم به سایت شناسه کاربری رو درست کنه مثلا autho 0 که مثلا 100 تا سامانه توی یه جا و 50 تا سامانه توی یه جای دیگه که همه ی اینهها برای یه سازمان هستش رو میتونه هندل کنه
اونجا issuer معنی داره
خوب audinec میشه همون پروژه شرکت خودمون اسمش
خوب توکن رو درست میکنیم یه Expire date هم بزاریم
خوب 24 ساعت اوکیه ولی 20 خیلی خوبه
خوب برای این که این شی که بیاد sign رو انجام بده و اون داستان ها نیاز داریم به jwt security token handler
و حالا اون رو ساختیم jwt security token handler رو بعدش بهش میگیم که بر اساس اون شی که اون بالا نوشته شده create token رو انجام بده
خوب حالا اون Securoty token که بهمون میده قالب json داره بهمون میده که این همونی که میریم توی سایت jwt میزنیم بهمون همه چیزشو میگه ولی ما میایم توی خط بعدی میزنیم و تبدلیلش میکنیم به string که بفرستیمش به user
خوب حالا میایم برای مدل خروجی که login داره اینطوری مینویسیم ، خوب میایم new میکنیم view models users رو که اون توی پارامتر های ورودیش یه user داشت و یه token که اینجا داریم بهش میدیم
خوب میرسیم به کنترلر
اولین Attr برای اینه که توی دسته api controller ها قرار بگیره و بعدیش برای اینه که بتونه route انجام بشه روش و چون داریم api میتونیسیم به جای controller از controller base اومدیم inherit کردیم
اینجا اومدیم از user service استفاده کردیم ، پس اینجا ما نیاز داریم بهش پس باید از di استفاده کنیم برای همین هم اومیدم یه constructor تعریف کردیم و ازش استفاده کردیم
اینجا چون نداریم null داده
اون قسمت ابی میشه امضا کار
خوب اینجا اومدیم به جای اون بالایی اومدیم iaction reuslt برگردونیدم که باهاش یه status code هم برگردونیم
خوب حالا میخوایم کامل ترش کنیم و میایم نوع اون iaction result رو هم تعیین کردیم
خوب
اینجا داریم تعریف میکنیم خروجی تابع login میتونه این دو حالت باشه یا تایپ 200 هستش و جنسش از نوع login response view mode یا 400 با تایپ error view model
خوب جالا توی middleware میخوایم ببینیم که اصلا توکنی با req ارسال شده یا خیر ، توکن ایا valid هست یا خیر ، اگر vlid هست آیا زمان داره یا خیر اگر همه این ها اوکی بود ایا این یوزر که اعلام کرده که داره رو ما هنوز توی دیتابیس داریم ؟ حالا اگر داریمش توی دیتابیس میریم اون رو برمیدارم و میزاریمش توی context عه
خوب req میاد بعد میره توی mid بعد توی mid توکن رو استخراج میکنیم بعدش میره توی attr (یا همون سره Action ) اونجا چک میشه که این یوزره به این قسمت دسترسی داره یا نه ، حالا اگر دسترسی داشت تازه وارد action میشه
اگر هم که Attr نداشت که وارد Action میشه
خوب توی mid یه constructor مینوشتیم که حداقل یه next لازم داشت
حالا اینجا هم از option میخوایم استفاده کنیم ، اورمدیمش
داخل mid باید یه تابعی بنویسیم به اسم invoke , و داخلش اومدیم user service رو هم بهش inject کردیم
اون توکنی که قراره بیاد توی هدرهاش هست
خوب body میشه json
خوب این body یه هدر هم داره که معمولا ما توکن میزاریم توی هدرش
اینطوری هم میشه ولی خوب نیست
خوب اونچیزی هم که توی هدر Set میشه برای این قضیه اسمش
خوب داریم میگیم که برو توی هدر رو ببین که آیا چیزی به این اسم وجود داره یا نه ، بعد بریزش توی request headres
میخوایم bearer توکن رو از توش استخراح کنیم
اینطوری میایم و space رو split میکنیم و اخرش رو جدا میکنیم اون توکن نهایی رو به ما میده
یه قسمت دیگه هم داریم به اسم authoriathon که این هم توی هدر set میشه 14:51
بعد گفتیم که اگر null یا null string بود برو کار بعدی و کاری نداشته باش این یعنی این که توی قسمت context هیچ اتفاقی نمیوفته یعنی توی context دیگه نمیره user رو اضافه کنه و خالی میمونه
حالا اکر مخالف null بود میره داخل این if عه که اونجا میایم میگیم که بیا با این token که برو توش رو نگاه کن و برو user اش رو بگیر و بعد برو توی دیتابیس چکش کن ، اگر پیداش کردی و اوکی بود بیا اون رو بچسبون به context ، خوب ما اینجا context و user service رو میفرستیم و توکن و میفرستیم و یکی هم کلید رو میفرستیم که بره با این کلید چک کنه ببینه signed اش درسته یا خیر
خوب بعدش میره توی این تابع بالایی که برای چک کردنش میایم از Validate token استفاده میکنیم و یه پارامتری هم بهش set میکنیم :
خوب اینجا میخوایم sign in key رو میخوایم چک کنیم برای همین true دادیمش
خوب بعدش میخوایم issuer sign in key رو محاسبه کنیم که برای این کار میایم از همون symetric security key استفاده میکنیم که اونجا key اش در بالاتر درست کردیم
اینجا هم اکگر این رو ننویسیم دیگه مفهوم validation و expiration time کار نمیکنه و از بین میره ، اینجا داره تاریخ رو صفر میکنه و زمان رو
خوب حالا میگه که بیاد و چک کنه ببینه که این validation token از جنس jwt security token هستش یا نه
خوب اگر به هر دلیلی مشکل داشت که هیچی یا expire شده باشه
برای همین کل این تابعی که داره چک میکنه رو توی try catch گذاشته
حالا اگر توکن null نبود ، میایم claim هاش رو از توی اون توکن میاریم بیرون، خوب اون چیزی که نیاز داریم name id یا همون id که user داره
خوب حالا اگر اون user id مشکل داشت دوباره Retuen میکنیم :
خوب حالا اگر user id اوکی بود میره داخل :
و پیداش میکنیم اینطوری
اگر هم نبود که دوباره retun میکنیم
خوب حالا اگر همه ی اینها اوکی بود دیگه میاد توی context یه آیتم به اسم user میزاریم و = میزارمیش با dounded user
خوب ما از این توی on authenticatin ازش استفاده میکنم :
حالا میریم برای یکی از این action ها این Attr رو میزاریم
در حالت درست