JavaRush /وبلاگ جاوا /Random-FA /JAAS - مقدمه ای بر فناوری (قسمت 1)
Viacheslav
مرحله

JAAS - مقدمه ای بر فناوری (قسمت 1)

در گروه منتشر شد
امنیت دسترسی مدت زیادی است که در جاوا پیاده سازی شده است و معماری ارائه این امنیت را JAAS - Java Authentication and Authorization Service نامیده می شود. این بررسی سعی خواهد کرد راز این که احراز هویت، مجوز چیست و JAAS چه ارتباطی با آن دارد، آشکار کند. چگونه JAAS با Servlet API دوست است و کجا در روابط خود مشکل دارند.
JAAS - مقدمه ای بر فناوری (قسمت 1) - 1

معرفی

در این بررسی می خواهم درباره موضوعی مانند امنیت برنامه های وب بحث کنم. جاوا دارای چندین فناوری است که امنیت را فراهم می کند:
  • " معماری امنیتی پلتفرم جاوا SE "، جزئیات بیشتر در مورد آن را می توان در راهنمای Oracle بخوانید: " معماری امنیتی پلتفرم JavaTM SE ". این معماری توضیح می دهد که چگونه باید برنامه های جاوا خود را در محیط اجرا Java SE ایمن کنیم. اما این موضوع بحث امروز ما نیست.

  • " معماری رمزنگاری جاوا " یک برنامه افزودنی جاوا است که رمزگذاری داده ها را توصیف می کند. می‌توانید در بررسی « معماری رمزنگاری جاوا: اولین آشنایی » یا در راهنمای Oracle: « راهنمای مرجع معماری رمزنگاری جاوا (JCA) » درباره این افزونه در JavaRush اطلاعات بیشتری کسب کنید.

اما گفتگوی امروز ما در مورد فناوری دیگری خواهد بود که "سرویس احراز هویت و مجوز جاوا (JAAS)" نام دارد. این اوست که موارد مهمی مانند احراز هویت و مجوز را توصیف می کند. بیایید به این موضوع با جزئیات بیشتری نگاه کنیم.
JAAS - مقدمه ای بر فناوری (قسمت 1) - 2

JAAS

JAAS یک برنامه افزودنی برای Java SE است و در راهنمای مرجع سرویس احراز هویت و مجوز جاوا (JAAS) توضیح داده شده است . همانطور که از نام فناوری پیداست، JAAS نحوه انجام احراز هویت و مجوز را توضیح می دهد:
  • " Authentication ": ترجمه شده از یونانی، "authentikos" به معنای "واقعی، واقعی" است. یعنی احراز هویت یک آزمون اصالت است. اینکه هرکسی که احراز هویت می‌شود، واقعاً همانی است که می‌گوید.

  • " مجوز ": ترجمه شده از انگلیسی به معنای "اجازه" است. یعنی مجوز کنترل دسترسی است که پس از احراز هویت موفقیت آمیز انجام می شود.

یعنی JAAS در مورد تعیین اینکه چه کسی درخواست دسترسی به یک منبع را دارد و تصمیم گیری در مورد اینکه آیا می تواند این دسترسی را به دست آورد یا خیر، است. یک تشبیه کوچک از زندگی: شما در امتداد جاده رانندگی می کنید و یک بازرس شما را متوقف می کند. لطفا اسناد - احراز هویت را ارائه دهید. آیا می توانید با اسناد - مجوز رانندگی کنید. یا مثلاً می خواهید از یک فروشگاه الکل بخرید. ابتدا از شما گذرنامه - احراز هویت خواسته می شود. در مرحله بعد، بر اساس سن شما، تصمیم گرفته می شود که آیا شما واجد شرایط خرید الکل هستید یا خیر. این مجوز است. در برنامه های تحت وب، ورود به عنوان کاربر (وارد کردن نام کاربری و رمز عبور) احراز هویت است. و تعیین اینکه کدام صفحات را می توانید باز کنید با مجوز تعیین می شود. اینجاست که "سرویس احراز هویت و مجوز جاوا (JAAS)" به ما کمک می کند. هنگام در نظر گرفتن JAAS، درک چندین مفهوم کلیدی که JAAS توصیف می کند مهم است: موضوع، اصول، اعتبار. موضوع موضوع احراز هویت است. یعنی حامل یا دارنده حقوق است. در مستندات، موضوع به عنوان منبع درخواست برای انجام برخی اقدامات تعریف شده است. موضوع یا منبع باید به نحوی شرح داده شود و برای این منظور از Principal استفاده می شود که در روسی گاهی اوقات به آن Principal نیز می گویند. یعنی هر Principal بازنمایی یک موضوع از دیدگاه خاصی است. برای روشن تر شدن موضوع، مثالی می زنیم: یک شخص معین یک سوژه است. و موارد زیر می توانند به عنوان اصلی عمل کنند:
  • گواهینامه رانندگی او به عنوان نماینده شخصی به عنوان کاربر جاده
  • پاسپورت او، به عنوان نماینده یک فرد به عنوان شهروند کشورش
  • گذرنامه خارجی او به عنوان نماینده یک شخص به عنوان شرکت کننده در روابط بین الملل
  • کارت کتابخانه او در کتابخانه، به عنوان نماینده یک شخص به عنوان خواننده متصل به کتابخانه
علاوه بر این، موضوع دارای مجموعه ای از "Credential" است که در انگلیسی به معنای "هویت" است. این گونه است که سوژه تأیید می کند که او است. به عنوان مثال رمز عبور کاربر می تواند Credential باشد. یا هر شیئی که با آن کاربر بتواند تأیید کند که واقعاً اوست. اکنون بیایید ببینیم که JAAS چگونه در برنامه های کاربردی وب استفاده می شود.
JAAS - مقدمه ای بر فناوری (قسمت 1) - 3

برنامه تحت وب

بنابراین، ما به یک برنامه وب نیاز داریم. سیستم ساخت پروژه خودکار Gradle به ما در ایجاد آن کمک می کند. به لطف استفاده از Gradle، ما می‌توانیم با اجرای دستورات کوچک، یک پروژه جاوا را در قالبی که نیاز داریم مونتاژ کنیم، ساختار دایرکتوری لازم را به‌طور خودکار ایجاد کنیم و موارد دیگر. می‌توانید اطلاعات بیشتری در مورد Gradle در نمای کلی کوتاه بخوانید: " معرفی مختصر بر Gradle " یا در مستندات رسمی " Gradle Getting Started ". ما باید پروژه را مقدار دهی اولیه کنیم (Initialization) و برای این منظور Gradle یک پلاگین ویژه دارد: " Gradle Init Plugin " (Init مخفف Initialization، به خاطر سپردن آسان است). برای استفاده از این افزونه، دستور را در خط فرمان اجرا کنید:
gradle init --type java-application
پس از اتمام موفقیت آمیز، یک پروژه جاوا خواهیم داشت. اکنون بیلد اسکریپت پروژه خود را برای ویرایش باز می کنیم. اسکریپت ساخت فایلی به نام است build.gradleکه تفاوت های ظریف ساخت برنامه را توصیف می کند. از این رو نام، ساخت اسکریپت. می توان گفت که این یک اسکریپت ساخت پروژه است. Gradle ابزار همه کاره ای است که قابلیت های اولیه آن با افزونه ها گسترش می یابد. بنابراین، اول از همه، بیایید به بلوک "پلاگین ها" توجه کنیم:
plugins {
    id 'java'
    id 'application'
}
به طور پیش فرض، Gradle، مطابق با آنچه که ما تعیین کردیم --type java-application، مجموعه ای از پلاگین های اصلی را تنظیم کرده است، یعنی آن پلاگین هایی که در توزیع خود Gradle گنجانده شده اند. اگر در وب‌سایت gradle.org به بخش «اسناد» (یعنی مستندات) بروید ، در سمت چپ در فهرست موضوعات در بخش «مرجع»، بخش « افزونه‌های اصلی » را می‌بینیم. بخش با شرح این افزونه های بسیار ابتدایی. بیایید دقیقاً افزونه هایی را انتخاب کنیم که به آن نیاز داریم، نه آنهایی که Gradle برای ما تولید کرده است. با توجه به مستندات، " پلاگین جاوا Gradle " عملیات اساسی با کد جاوا، مانند کامپایل کد منبع را ارائه می دهد. همچنین، طبق مستندات، " افزونه اپلیکیشن Gradle " ابزارهایی را برای کار با "برنامه اجرایی JVM" در اختیار ما قرار می دهد. با یک برنامه جاوا که می تواند به عنوان یک برنامه مستقل راه اندازی شود (به عنوان مثال، یک برنامه کنسول یا یک برنامه با رابط کاربری خاص خود). به نظر می رسد که ما به پلاگین "برنامه" نیازی نداریم، زیرا ... ما به یک برنامه مستقل نیاز نداریم، ما به یک برنامه وب نیاز داریم. بیا حذفش کنیم و همچنین تنظیمات "mainClassName" که فقط برای این افزونه شناخته شده است. علاوه بر این، در همان بخش « بسته‌بندی و توزیع » که پیوند مستندات Application Plugin ارائه شده است، پیوندی به پلاگین Gradle War وجود دارد. پلاگین Gradle War همانطور که در مستندات ذکر شده است، از ایجاد برنامه های وب جاوا در قالب جنگ پشتیبانی می کند. در فرمت WAR به این معنی است که به جای یک آرشیو JAR، یک آرشیو WAR ایجاد می شود. به نظر می رسد که این همان چیزی است که ما نیاز داریم. همچنین، همانطور که در مستندات آمده است، "افزونه جنگ افزونه جاوا را گسترش می دهد". یعنی می توانیم افزونه java را با افزونه war جایگزین کنیم. بنابراین، بلوک افزونه ما در نهایت به این صورت خواهد بود:
plugins {
    id 'war'
}
همچنین در مستندات مربوط به "Plugin War Gradle" گفته شده است که این افزونه از یک "Project Layout" اضافی استفاده می کند. Layout از انگلیسی به عنوان مکان ترجمه شده است. یعنی افزونه war به طور پیش فرض انتظار وجود مکان مشخصی از فایل ها را دارد که برای وظایف خود از آن استفاده خواهد کرد. از دایرکتوری زیر برای ذخیره فایل های برنامه وب استفاده می کند: src/main/webapp رفتار افزونه به شرح زیر است:
JAAS - مقدمه ای بر فناوری (قسمت 1) - 4
یعنی این افزونه هنگام ساخت آرشیو WAR برنامه وب ما، فایل‌های این مکان را در نظر می‌گیرد. علاوه بر این، اسناد پلاگین جنگ Gradle می گوید که این دایرکتوری "ریشه بایگانی" خواهد بود. و در حال حاضر در آن می توانیم یک دایرکتوری WEB-INF ایجاد کنیم و فایل web.xml را در آنجا اضافه کنیم. این چه نوع فایلی است؟ web.xml- این یک "Deployment Descriptor" یا "Deployment Descriptor" است. این فایلی است که نحوه پیکربندی برنامه وب ما برای کار را توضیح می دهد. این فایل مشخص می‌کند که برنامه ما به چه درخواست‌هایی رسیدگی می‌کند، تنظیمات امنیتی و موارد دیگر. در هسته خود، تا حدودی شبیه به یک فایل مانیفست از یک فایل JAR است (به " کار با فایل های مانیفست: پایه ها " مراجعه کنید. فایل Manifest نحوه کار با یک برنامه جاوا (به عنوان مثال یک بایگانی JAR) را نشان می دهد و web.xml نحوه کار با یک برنامه وب جاوا (یعنی آرشیو WAR) را می گوید. مفهوم "Deployment Descriptor" به خودی خود بوجود نیامده است، بلکه در سند " Servlet API Specification" توضیح داده شده است.". هر برنامه وب جاوا به این "API Servlet" بستگی دارد. درک این نکته مهم است که این یک API است - یعنی شرحی از قراردادهای تعاملی است. برنامه های کاربردی وب برنامه های مستقل نیستند. آنها بر روی یک وب سرور اجرا می شوند. که ارتباط شبکه ای را با کاربران فراهم می کند. یعنی وب سرور نوعی "کانتینر" برای برنامه های کاربردی وب است. این منطقی است، زیرا می خواهیم منطق یک برنامه وب را بنویسیم، یعنی کاربر چه صفحاتی را خواهد دید و چگونه می بیند. آنها باید به اقدامات کاربر واکنش نشان دهند و ما نمی خواهیم کدی برای نحوه ارسال پیام به کاربر، نحوه انتقال بایت اطلاعات و سایر موارد سطح پایین و بسیار با کیفیت بنویسیم. به نظر می رسد که برنامه های وب همه متفاوت هستند، اما انتقال داده ها یکسان است. یعنی یک میلیون برنامه نویس باید بارها و بارها برای یک هدف مشابه بنویسند. بنابراین وب سرور مسئول برخی از تعاملات کاربر است. و تبادل داده، و برنامه وب و توسعه دهنده مسئول تولید آن داده ها هستند. و برای اتصال این دو قسمت یعنی. وب سرور و برنامه وب، شما نیاز به یک قرارداد برای تعامل آنها دارید، یعنی. برای انجام این کار از چه قوانینی پیروی خواهند کرد؟ Servlet API اختراع شد تا به نوعی قرارداد را توصیف کنیم، تعامل بین یک برنامه وب و یک وب سرور چگونه باید باشد. جالب اینجاست که حتی اگر از فریم‌ورک‌هایی مانند Spring استفاده می‌کنید، باز هم یک Servlet API در زیر هود اجرا می‌شود. یعنی شما از Spring استفاده می کنید و Spring با Servlet API برای شما کار می کند. به نظر می رسد که پروژه برنامه وب ما باید به Servlet API بستگی داشته باشد. در این حالت Servlet API یک وابستگی خواهد بود. همانطور که می دانیم، Gradle همچنین به شما اجازه می دهد تا وابستگی های پروژه را به صورت اعلامی توصیف کنید. پلاگین ها نحوه مدیریت وابستگی ها را توضیح می دهند. به عنوان مثال، پلاگین Java Gradle یک روش مدیریت وابستگی "testImplementation" را معرفی می کند که می گوید چنین وابستگی فقط برای تست ها لازم است. اما پلاگین Gradle War یک روش مدیریت وابستگی "providedCompile" اضافه می کند که می گوید چنین وابستگی در آرشیو WAR برنامه وب ما گنجانده نمی شود. چرا Servlet API را در آرشیو WAR خود قرار نمی دهیم؟ زیرا Servlet API توسط خود وب سرور در اختیار برنامه وب ما قرار خواهد گرفت. اگر یک وب سرور یک Servlet API ارائه دهد، سرور یک servlet container نامیده می شود. بنابراین، این وظیفه وب سرور است که Servlet API را در اختیار ما قرار دهد و این وظیفه ماست که ServletAPI را فقط در زمان کامپایل کد ارائه کنیم. از همین رو providedCompile. بنابراین، بلوک وابستگی ها به شکل زیر خواهد بود:
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testImplementation 'junit:junit:4.12'
}
بنابراین، اجازه دهید به فایل web.xml برگردیم. به طور پیش فرض، Gradle هیچ Deployment Descriptor ایجاد نمی کند، بنابراین باید خودمان این کار را انجام دهیم. بیایید یک دایرکتوری ایجاد کنیم src/main/webapp/WEB-INFو در آن یک فایل XML به نام ایجاد کنیم web.xml. حالا بیایید خود "مشخصات Servlet Java" و فصل " Chapter 14 Deployment Descriptor " را باز کنیم. همانطور که در "14.3 Deployment Descriptor" بیان شد، سند XML Deployment Descriptor توسط طرح http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd توضیح داده شده است . یک طرح XML توضیح می دهد که یک سند از چه عناصری می تواند تشکیل شده باشد و به چه ترتیبی باید ظاهر شوند. کدام اجباری است و کدام نه. به طور کلی، ساختار سند را توصیف می کند و به شما امکان می دهد بررسی کنید که آیا سند XML به درستی ترکیب شده است یا خیر. حالا بیایید از مثال فصل " 14.5 مثال " استفاده کنیم، اما این طرح باید برای نسخه 3.1 مشخص شود، یعنی.
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
خالی ما web.xmlبه این صورت خواهد بود:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>JAAS Example</display-name>
</web-app>
بیایید اکنون سروری را که با استفاده از JAAS از آن محافظت خواهیم کرد، توضیح دهیم. قبلاً Gradle کلاس App را برای ما ایجاد کرد. بیایید آن را به یک servlet تبدیل کنیم. همانطور که در مشخصات در " فصل 2 رابط Servlet " بیان شد، که " برای بیشتر اهداف، توسعه دهندگان HttpServlet را برای پیاده سازی servlet های خود گسترش می دهند "، یعنی برای تبدیل یک کلاس به servlet، باید این کلاس را از HttpServlet:
public class App extends HttpServlet {
	public String getGreeting() {
        return "Secret!";
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print(getGreeting());
    }
}
همانطور که گفتیم Servlet API یک قرارداد بین سرور و برنامه وب ما است. این قرارداد به ما این امکان را می دهد که توضیح دهیم زمانی که کاربر با سرور تماس می گیرد، سرور درخواستی را از کاربر در قالب یک شی ایجاد می کند HttpServletRequestو آن را به servlet ارسال می کند. همچنین یک شی در اختیار سرورلت قرار می دهد HttpServletResponseتا سرولت بتواند پاسخی به آن برای کاربر بنویسد. پس از اتمام اجرای servlet، سرور قادر خواهد بود بر اساس آن پاسخی را به کاربر ارائه دهد HttpServletResponse. یعنی سرولت مستقیما با کاربر ارتباط برقرار نمی کند و فقط با سرور ارتباط برقرار می کند. برای اینکه سرور بداند که ما یک servlet داریم و برای چه درخواست هایی باید از آن استفاده شود، باید این را در Deployment Descriptor به سرور بگوییم:
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>jaas.App</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/secret</url-pattern>
</servlet-mapping>
در این حالت، تمام درخواست‌ها با نام به یک سرور ما که مربوط به کلاس است، /secretخطاب نمی‌شوند . همانطور که قبلاً گفتیم، یک برنامه وب فقط می تواند بر روی یک وب سرور مستقر شود. وب سرور را می توان به طور جداگانه (مستقل) نصب کرد. اما برای اهداف این بررسی، یک گزینه جایگزین مناسب است - در حال اجرا بر روی یک سرور تعبیه شده. این بدان معنی است که سرور به صورت برنامه نویسی ایجاد و راه اندازی می شود (افزونه این کار را برای ما انجام می دهد) و در همان زمان برنامه وب ما روی آن مستقر می شود. سیستم ساخت Gradle به شما امکان می دهد از پلاگین Gradle Gretty Plugin برای این اهداف استفاده کنید: appjaas.App
plugins {
    id 'war'
    id 'org.gretty' version '2.2.0'
}
علاوه بر این، افزونه Gretty مستندات خوبی دارد . بیایید با این واقعیت شروع کنیم که افزونه Gretty به شما امکان می دهد بین وب سرورهای مختلف جابجا شوید. این با جزئیات بیشتر در مستندات توضیح داده شده است: " تغییر بین ظروف سرولت ". بیایید به تامکت سوئیچ کنیم، زیرا ... این یکی از محبوب ترین ها در استفاده است، و همچنین دارای اسناد خوب و مثال های زیادی است و مشکلات تجزیه و تحلیل شده است:
gretty {
    // Переключаемся с дефолтного Jetty на Tomcat
    servletContainer = 'tomcat8'
    // Укажем Context Path, он же Context Root
    contextPath = '/jaas'
}
اکنون می توانیم "gradle appRun" را اجرا کنیم و سپس برنامه وب ما در http://localhost:8080/jaas/secret در دسترس خواهد بود.
JAAS - مقدمه ای بر فناوری (قسمت 1) - 5
مهم است که بررسی کنید که ظرف سرولت توسط تامکت انتخاب شده باشد (به شماره 1 مراجعه کنید) و بررسی کنید که برنامه وب ما در کدام آدرس موجود است (نگاه کنید به شماره 2).
JAAS - مقدمه ای بر فناوری (قسمت 1) - 6

احراز هویت

تنظیمات احراز هویت اغلب از دو بخش تشکیل شده است: تنظیمات در سمت سرور و تنظیمات در سمت برنامه وب که روی این سرور اجرا می شود. تنظیمات امنیتی یک برنامه وب نمی‌تواند با تنظیمات امنیتی وب سرور تعامل نداشته باشد، اگر به دلیل دیگری یک برنامه وب نمی‌تواند با وب سرور تعامل داشته باشد. بیهوده بود که به تامکت روی آوردیم، زیرا... تامکت معماری خوبی دارد (به " معماری آپاچی تامکت 8 " مراجعه کنید). از توضیحات این معماری مشخص می شود که تامکت به عنوان یک وب سرور، برنامه وب را به عنوان یک زمینه خاص نشان می دهد که به آن " محور تامکت " می گویند. این زمینه به هر برنامه وب اجازه می دهد تا تنظیمات خاص خود را داشته باشد، جدا از سایر برنامه های کاربردی وب. علاوه بر این، برنامه وب می تواند بر تنظیمات این زمینه تأثیر بگذارد. انعطاف پذیر و راحت. برای درک عمیق‌تر، توصیه می‌کنیم مقاله « درک ظروف زمینه تامکت » و بخش مستندات تامکت « کانتینر زمینه » را مطالعه کنید. همانطور که در بالا گفته شد، برنامه وب ما می تواند با استفاده از یک تامکت متن برنامه ما را تحت تاثیر قرار دهد /META-INF/context.xml. و یکی از تنظیمات بسیار مهمی که می توانیم بر آن تأثیر بگذاریم، قلمروهای امنیتی است. قلمروهای امنیتی نوعی "منطقه امنیتی" است. منطقه ای که تنظیمات امنیتی خاصی برای آن مشخص شده است. بر این اساس، هنگام استفاده از یک قلمرو امنیتی، تنظیمات امنیتی تعریف شده برای این قلمرو را اعمال می کنیم. قلمروهای امنیتی توسط یک کانتینر مدیریت می شوند، یعنی. وب سرور، نه برنامه وب ما. ما فقط می توانیم به سرور بگوییم که کدام حوزه امنیتی باید به برنامه ما گسترش یابد. مستندات Tomcat در بخش " The Realm Component " یک قلمرو را به عنوان مجموعه ای از داده ها در مورد کاربران و نقش آنها برای انجام احراز هویت توصیف می کند. Tomcat مجموعه ای از پیاده سازی های مختلف Security Realm را ارائه می دهد که یکی از آنها " Jas Realm " است. با درک کمی اصطلاحات، بیایید زمینه Tomcat را در فایل توضیح دهیم /META-INF/context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Realm className="org.apache.catalina.realm.JAASRealm"
           appName="JaasLogin"
           userClassNames="jaas.login.UserPrincipal"
           roleClassNames="jaas.login.RolePrincipal"
           configFile="jaas.config" />
</Context>
appName- نام نرم افزار. Tomcat سعی خواهد کرد این نام را با نام های مشخص شده در configFile. configFile- این "فایل پیکربندی ورود" است. نمونه ای از این را می توان در مستندات JAAS مشاهده کرد: " پیوست B: نمونه تنظیمات ورود ". علاوه بر این، مهم است که این فایل ابتدا در منابع جستجو شود. بنابراین وب اپلیکیشن ما خودش می تواند این فایل را ارائه دهد. ویژگی ها userClassNamesو roleClassNamesحاوی نشانه ای از کلاس هایی است که نشان دهنده اصل کاربر است. JAAS مفاهیم "کاربر" و "نقش" را به عنوان دو مفهوم متفاوت از هم جدا می کند java.security.Principal. بیایید کلاس های فوق را شرح دهیم. بیایید ساده ترین پیاده سازی را برای کاربر اصلی ایجاد کنیم:
public class UserPrincipal implements Principal {
    private String name;
    public UserPrincipal(String name) {
        this.name = name;
    }
    @Override
    public String getName() {
        return name;
    }
}
ما دقیقا همان پیاده سازی را برای RolePrincipal. همانطور که از رابط می بینید، نکته اصلی برای Principal ذخیره و برگرداندن نام (یا ID) است که نشان دهنده اصلی است. اکنون، ما یک قلمرو امنیتی داریم، کلاس‌های اصلی داریم. باقی مانده است که فایل را از configFileویژگی " "، با نام مستعار پر کنید login configuration file. شرح آن را می توان در مستندات Tomcat یافت: " The Realm Component ".
JAAS - مقدمه ای بر فناوری (قسمت 1) - 7
یعنی ما می توانیم تنظیمات JAAS Login Config را در منابع برنامه وب خود قرار دهیم و به لطف Tomcat Context می توانیم از آن استفاده کنیم. این فایل باید به عنوان یک منبع برای ClassLoader در دسترس باشد، بنابراین مسیر آن باید به این صورت باشد: \src\main\resources\jaas.config بیایید محتویات این فایل را تنظیم کنیم:
JaasLogin {
    jaas.login.JaasLoginModule required debug=true;
};
شایان ذکر است که context.xmlاز همین نام در اینجا و در استفاده می شود. این قلمرو امنیتی را به LoginModule نگاشت می کند. بنابراین، Tomcat Context به ما گفت که کدام کلاس‌ها نماینده اصلی هستند، و همچنین از کدام LoginModule استفاده کنیم. تنها کاری که باید انجام دهیم این است که این LoginModule را پیاده سازی کنیم. LoginModule شاید یکی از جالب ترین چیزها در JAAS باشد. اسناد رسمی به ما در توسعه LoginModule کمک می کند: " Java Authentication and Authorization Service (JAAS): LoginModule Developer's Guide ". بیایید ماژول ورود را پیاده سازی کنیم. بیایید یک کلاس ایجاد کنیم که رابط را پیاده سازی کند LoginModule:
public class JaasLoginModule implements LoginModule {
}
ابتدا روش اولیه سازی را شرح می دهیم LoginModule:
private CallbackHandler handler;
private Subject subject;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, <String, ?> sharedState, Map<String, ?> options) {
	handler = callbackHandler;
	this.subject = subject;
}
این روش ذخیره می‌کند Subject، که ما آن را بیشتر احراز هویت می‌کنیم و با اطلاعات مربوط به اصول پر می‌کنیم. ما همچنین برای استفاده های بعدی CallbackHandlerکه به ما داده شده است، ذخیره خواهیم کرد. با کمک، CallbackHandlerکمی بعد می توانیم اطلاعات مختلفی در مورد موضوع احراز هویت درخواست کنیم. CallbackHandlerمی‌توانید در بخش مربوط به اسناد اطلاعات بیشتری در مورد آن بخوانید: " راهنمای مرجع JAAS: CallbackHandler ". سپس روش loginاحراز هویت اجرا می شود Subject. این مرحله اول احراز هویت است:
@Override
public boolean login() throws LoginException {
	// Добавляем колбэки
	Callback[] callbacks = new Callback[2];
	callbacks[0] = new NameCallback("login");
	callbacks[1] = new PasswordCallback("password", true);
	// При помощи колбэков получаем через CallbackHandler логин и пароль
	try {
		handler.handle(callbacks);
		String name = ((NameCallback) callbacks[0]).getName();
		String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
		// Далее выполняем валидацию.
		// Тут просто для примера проверяем определённые значения
		if (name != null && name.equals("user123") && password != null && password.equals("pass123")) {
			// Сохраняем информацию, которая будет использована в методе commit
			// Не "пачкаем" Subject, т.к. не факт, что commit выполнится
			// Для примера проставим группы вручную, "хардcodeно".
			login = name;
			userGroups = new ArrayList<String>();
			userGroups.add("admin");
			return true;
		} else {
			throw new LoginException("Authentication failed");
		}
	} catch (IOException | UnsupportedCallbackException e) {
		throw new LoginException(e.getMessage());
	}
}
مهم این است که loginما نباید آن را تغییر دهیم Subject. چنین تغییراتی فقط باید در روش تأیید رخ دهد commit. در مرحله بعد، ما باید روش تایید احراز هویت موفق را شرح دهیم:
@Override
public boolean commit() throws LoginException {
	userPrincipal = new UserPrincipal(login);
	subject.getPrincipals().add(userPrincipal);
	if (userGroups != null && userGroups.size() > 0) {
		for (String groupName : userGroups) {
			rolePrincipal = new RolePrincipal(groupName);
			subject.getPrincipals().add(rolePrincipal);
		}
	}
	return true;
}
شاید جدا کردن روش loginو commit. اما نکته اینجاست که ماژول های لاگین را می توان ترکیب کرد. و برای احراز هویت موفقیت آمیز ممکن است لازم باشد چندین ماژول ورود با موفقیت کار کنند. و تنها در صورتی که تمام ماژول های لازم کار کرده باشند، تغییرات را ذخیره کنید. این مرحله دوم احراز هویت است. بیایید با abortو متدها تمام کنیم logout:
@Override
public boolean abort() throws LoginException {
	return false;
}
@Override
public boolean logout() throws LoginException {
	subject.getPrincipals().remove(userPrincipal);
	subject.getPrincipals().remove(rolePrincipal);
	return true;
}
این روش abortزمانی فراخوانی می شود که مرحله اول احراز هویت ناموفق باشد. این روش logoutزمانی فراخوانی می شود که سیستم از سیستم خارج شود. پس از پیاده سازی Login Moduleو پیکربندی آن Security Realm، اکنون باید web.xmlاین واقعیت را مشخص کنیم که می خواهیم از یک مورد خاص استفاده کنیم Login Config:
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>JaasLogin</realm-name>
</login-config>
ما نام قلمرو امنیتی خود را مشخص کردیم و روش احراز هویت - BASIC را مشخص کردیم. این یکی از انواع احراز هویت است که در Servlet API در بخش " 13.6 Authentication " توضیح داده شده است. باقی ماند n
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION