شروع سریع Spring Security (قسمت اول)

سلام دوستان طبق روال همیشه بدون مقدمه میرم سر اصل داستان. برای شروع آموزش باید Spring boot رو بلد باشین تا بتونین درست مراحل رو اجراکنید و به نتیجه برسین. خب همونجوری که احتمالا حدس میزنید سکیوریتی برای اعمال فرایندهای احراز هویت کاربر به هر طریقی که تاحالا دیدید از قبیل فرم‌لاگین ، توکن ، لاگین با شبکه‌های اجتماعی مختلف و ... . و همچنین authorize کردن کاربر یعنی مشخص کردن اینکه کدوم کاربر اجازه انجام چه کارهایی رو داره ایجاد شده.خب تصور کنید یه وب اپلیکیشن دارید که مثلا یه لیست کانتکت نشون میده (یا هرچیز دیگه‌ای) که میشه عملیات CRUD رو روش انجام داد.خب درحال حاضر هرکسی میتونه لیست رو تغییر بده و ما نیاز داریم که براش سیستم ادمین درست کنیم و بگیم آدمایی که Authenticate شدن (ما میشناسیمشون) بتونن لیست رو تغییر بدن و بقیه فقط بتونن تماشا کنن :).مرحله اول اضافه کردن سکیوریتی به پروژه‌س. من maven استفاده میکنم که کدش این شکلی میشه :<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>بدون اینکه کار اضافه‌تری انجام بدیم اگه یسر به اپمون بزنیم (درحالی که ریستارت کردیم سرور رو) میبنیم که یه فرم لاگین نشونمون میده :) .فقط مشکل اینجاست که همه مسیرهای اپمون به لاگین نیاز داره و محافظت میشه که ما اینو نمیخوایم و میخوایم لیستمون پابلیک باشه.یه نکته‌ای ام بگم که الان یه یوزر هم به اسم admin خودش ساخته و پسوردشم تو لاگتون بگردید میبینید (زیاد درگیرش نشید و ادامه رو بخونید بدرد بخور نیست زیاد)خب بریم سر اینکه چجوری میشه مسیرهایی که میخوایم آزاد باشند رو به سکیوریتی بگیم.برای اینکار نیاز دارید یه کلاس بسازید و کلاس‌ابسترکتِ WebSecurityConfigurerAdapter رو extend کنید.و از انوتیشن @EnableWebSecurity استفاده کنید. اینجا مرکز کارهاییه که با سکیوریتی میتونید انجام بدید و تقریبا هرکار بخواید بکنید یه سری به این کلاس باید بزنید و اگر این کلاس رو خوب بفهمید خیلی کمک کنندس. مشخصا در ابتدا سه تا متد خیلی کوتاه و ساده باید اینجا بنویسید دوتاش متد configure عه و یکیش هم یک ‌‌‌‌Bean برای تعریف password encoder. پیاده سازی کلاس رو ببینیم که توضیح بدم روش:@EnableWebSecurity public class Config extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser(&quotadmin&quot) .password( passwordEncoder().encode(&quot1234&quot) ) .roles(&quotAdmin&quot) .authorities(&quotACCESS_CRUD&quot); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers( &quot/&quot).permitAll() .anyRequest().authenticated() .and() .formLogin(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }خب در متد اول ما اومدیم یوزر تعریف کردیم که الان شبیه متغیر ذخیره میشه و دیتابیس خاصی نداریم ، کلا اون متد برای تعریف دیتاسورس هست ، میشه درواقع اونجا بهش بگیم یوزرهارو چجوری باید پیدا کنه (تو قسمت دوم میگم چجوری از دیتابیس بخونید) . اما الان تمرکز کنید رو متد دوم اونجا ما روی آبجکت ‌HttpSecurity میتونیم کلی چیزای جالب تعریف کنیم. مثلا اینجا با صدا زدن متد authorizeRequests بهش میگیم که میخوایم مشخص کنیم کدوم مسیرها آزادن و کدوم‌ها باید محافظت بشن که با متد antMatchers اینکارو کردیمو مسیر روت(root) رو باز گذاشتیم و گفتیم بقیه مسیرها باید محافظت بشه (مسیرهای css و js هم باید باز میذاشتم ولی بخاطر سادگی کد اینکار رو نکردم چیزیه که خودتون بهش میرسین و نیازی به گفتن نیست) . یه متد and زدیم که دوباره آبجکت HttpSecurity رو بهمون میده و حالا براش رَوش احراز هویت رو مشخص کردیم و گفتیم از فرم لاگین‌ استفاده کن که الان از صفحه لاگین‌فرم دیفالتش استفاده میکنه (تو قسمت سوم میگم چجوری عوضش کنید خیلی سادس) . توی متد سوم هم اومدیم یه کلاس ‌encoder تعریف کردیم و برای پسورد ذخیره کردن ازش استفاده میکنیم (هم اینجا هم بعدا توی دیتابیس)حالا اپ ما داره درست کار میکنه و وقتی بریم داخلش مسیر "/" آزاده و بدون لاگین قابل مشاهدس و مابقی مسیرها نیاز به لاگین داره. ناگفته پیداس که میتونه مسیرهای آزاد بیشتر باشه و قوانین بیشتری روش اعمال بشه. اگه کدهای بالارو تست کردید حتما حدس میزنید که ما نیاز داریم یکسری مسیر‌هارو گروهی آزاد بذاریم و تا هم ما کمتر خسته‌شیم هم خواننده کد پس میتونیم تو antMatcher اینجوری‌هم بگیم.antMatchers( &quot/free/test1&quot , &quot/free/test2&quot ).permitAll() // OR .antMatchers( &quot/free/**&quot ).permitAll()اینجا قانونی که ما گذاشتیم فقط authenticate بودن بود اما باز ناگفته پیداس که سکیوریتی براساس role هم میتونه اجازه دسترسی بده که یعنی میتونه یه کاربر لاگین باشه اما به بخشهای دسترسی نداشته باشه و ۴۰۳ بگیره . ریز تر از اون براساس authority هم میتونه دسترسی بده. (authority به دسترسی‌های کوچک‌تر میگن معمولا یک ‌role یه دسته‌ای از authority هارا دارد و مثلا نقش Manager ممکنه اجازه EDIT_CONTACT را داشته باشد یا نداشته باشد ). برای مشخص کردن این قوانین هم کار سختی نداریم مثلا اینجا ما نقش Admin رو برای کاربرمون تعریف کردیم میتونیم اینجوری عمل کنیم :.anyRequest( &quot/&quot ).hasRole(&quotAdmin&quot) //OR .anyRequest( &quot/&quot ).hasAuthority(&quotACCESS_CRUD&quot)حواستون باشه دقیقا همون رشته‌ای که برای تعرف یوزر ازش استفاده کردید رو اینجاهم باید استفاده کنید که اشتباهی نشه.خب برای شروع کافیه تو قسمت بعدی میگم که چجوری از دیتابیس برای ذخیره کاربرها استفاده کنیم.امیدوارم مفید بوده باشه خوشحال میشم توی توئیترم بیشتر باهم معاشرت کنیم.