جاوا و تکنولوژی های آن

java programming language

در این وبلاگ به بررسی نکات موجود در جاوا و تکنولوژی های آن می پردازیم

طبقه بندی موضوعی


در قسمت قبل مقدمه ای در مورد احراز هویت و یک روش ابتدایی آنرا توضیح دادیم در این قسمت به پیاده سازی احراز هویت از نوع Basic و Digest روی URI یکسان میپردازیم 

هر دو روش از استاندارد های احراز هویت در RESTful هستند


در ابتدا لازم است نکته مهم را در خصوص استاندارد RESTful و Spring REST عنوان کنیم یک سرویس RESTful باید stateless باشد ولی چون هنوز مسئله حذف session در Spring بسیار سخت بوده است مخصوصا موقعی که تنظیمات بوسیله namespace انجام شود، Spring Security با اضافه کردن تنظیمات جدیدی به namespace موفق به ارائه راه حل استفاده نکردن از session شده است و تضمین میکند که هیچ session ای ایجاد و استفاده نخواهد شد و برای هر درخواست دریافت شده احراز هویت انجام خواهد شد



تنظیمات Basic Authentication :

برای ست کردن کردن تنظیمات ابتدا Entry Point های قبلی را که در تگ <http> ست کرده بودیم را حذف میکنیم 
<http create-session="stateless">
   <intercept-url pattern="/api/admin/**" access="ROLE_ADMIN" />
 
   <http-basic />
</http>

بکار بردن تگ <http-basic /> بتنهایی کافی است که BasicAuthenticationFilter و BasicAuthenticationEntryPoint را بسازد و انها را بهم مرتبط کند 



تنظیمات Digest Authentication : 


با تنظیمات قبلی شروع میکنیم ابتدا برای Digest Authentication نیاز است که Filter و entry point را به عنوان Bean هایی تعریف کنیم سپس digest entry point با چیزی که در تگ http-basic در پشت صحنه ساخته شده است override خواهد شد و در آخر Digest Filter مورد نظرمان بعد از basic authentication filter قرار میگیرد 


<http create-session="stateless" entry-point-ref="digestEntryPoint">
   <intercept-url pattern="/api/admin/**" access="ROLE_ADMIN" />
 
   <http-basic />
   <custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
</http>
 
<beans:bean id="digestFilter" class=
 "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
   <beans:property name="userDetailsService" ref="userService" />
   <beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
</beans:bean>
 
<beans:bean id="digestEntryPoint" class=
 "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
   <beans:property name="realmName" value="Contacts Realm via Digest Authentication"/>
   <beans:property name="key" value="acegi" />
</beans:bean>
 
<authentication-manager>
   <authentication-provider>
      <user-service id="userService">
         <user name="eparaschiv" password="eparaschiv" authorities="ROLE_ADMIN" />
         <user name="user" password="user" authorities="ROLE_USER" />
      </user-service>
   </authentication-provider>
</authentication-manager>

متاسفانه Digest Authentication همانند Basic Authentication بصورت اتوماتیک تنظیماتش ست نمیشود در Basic Authentication فقط کافی بود از <http-basic> استفاده کنیم ولی در Digest نیاز داریم که Bean هایی تعریف کنیم که به تنظیمات امنیتی متصل شوند 




حال چطور میتوان هر دو روش احراز هویت را در یک URI داشته باشیم :


در قبل دیدیم که هر روش بتنهایی چقدر ساده قابل تعریف بودند ولی اگر بخواهیم هر دو را در یک مسیر URI داشته باشیم یک لایه پیچیدگی به آن اضافه خواهد شد 



- زمانی که درخواست مشخصی ارسال میشود :


در هدر فیلد Authentication اگر با پیشوند Basic آغاز شده بود نوع Basic و اگر با پیشوند Digest آغاز شده بود نوع Digest در نظر گرفته میشود


- زمانی که یک درخواست غیر واضح ارسال میشود :


هر دو filter زمانی که یک درخواست بدون فیلد Authorization در هدر دریافت میکنند چون برای هر دو ناشناس است بدون انجام فرآیندی در ادامه زنجیره درخواست جلو خواهد رفت و در نهایت وقتی ببیند که درخواست بدون authentication است خطای AccessDeniedException  تولید و توسط ExceptionTranslationFilter گرفته میشود و کد 401 به کلاینت برای احراز هویت ارسال میشود

حال با همین سناریو و با مشخص کردن نوع احراز هویت میتوان در URI یکسان از هر دو روش بهره برد و اگر نوع authentication را مشخص نکنیم در Spring Security نوع Digest بصورت پیش فرض در نظر گرفته خواهد شد 




تست هر دو روش با URI یکسان :


@Test
public void givenAuthenticatedByBasicAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().preemptive().basic( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );
 
   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}
@Test
public void givenAuthenticatedByDigestAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().digest( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );
 
   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}


در تست دقت کنید که دفعه اول که احراز هویت انجام شد کاربر authenticate شده و در دفعه دوم نیاز است که تست را دوباره برای حالت بعدی راه اندازی کنید ولی اگر چنانچه درخواست دوم هم ارسال شد چالشی برای سرور ایجاد نمیکند چون آنرا بصورت  Digest در نظر میگیرد







نظرات  (۰)

هیچ نظری هنوز ثبت نشده است

ارسال نظر

ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی