Spring Security Simple Course




Tomcat nedir? 

**Tomcat** və ya tam adı ilə **Apache Tomcat**, Java proqramları üçün geniş istifadə olunan açıq mənbəli bir veb server və servlet konteyneridir. Apache Software Foundation tərəfindən inkişaf etdirilib və əsasən Java dilində yazılmış veb tətbiqləri işə salmaq üçün istifadə olunur.


### **Tomcat nədir və nə üçün istifadə olunur?**


- **Veb Server və Servlet Konteyneri**:

  - Tomcat, əsasən bir **servlet konteyneri** kimi işləyir. Bu, onun Java Servlet-lərini işə salmağa və JavaServer Pages (JSP) texnologiyası ilə yazılmış veb səhifələri göstərməyə imkan verməsi deməkdir.

  

- **Veb Tətbiqlərinin İdarə Edilməsi**:

  - Java ilə hazırlanmış veb tətbiqlərini Tomcat vasitəsilə asanlıqla yerləşdirə və idarə edə bilərsiniz. Yəni, Tomcat tətbiqlərinizi internet üzərindən istifadəçilərə çatdırmaq üçün bir platforma rolunu oynayır.


- **Java EE Standartlarını Dəstəkləyir**:

  - Tomcat, Java Enterprise Edition (Java EE) standartlarının bir hissəsi olan servlets, JSP və WebSocket kimi texnologiyaları dəstəkləyir. Bu onu Java ilə inkişaf etdirilən müəssisə səviyyəli tətbiqlərin yerləşdirilməsi üçün uyğun edir.


### **Tomcat-ın istifadəsi**


- Java ilə yazılmış veb tətbiqlərin yerləşdirilməsi və işlədilməsi.

- Kiçik və orta ölçülü layihələr üçün bir veb server kimi istifadə olunması.

- Java təlimləri və tədris məqsədləri üçün proqramçıların öz tətbiqlərini sınamaq üçün istifadə etməsi.


Qısacası, Tomcat Java tətbiqlərinin işlədilməsi üçün güclü və populyar bir vasitədir və həm inkişaf, həm də istehsal mühitlərində geniş istifadə olunur.



Servlet nedir?


**Servlet**, Java ilə yazılmış bir server tərəfli proqramdır və əsasən veb serverlərdə işləyərək dinamik veb məzmunu yaratmaq üçün istifadə olunur. Servlet-lər Java EE (Java Enterprise Edition) texnologiyasının bir hissəsidir və veb tətbiqlər üçün backend (arxa tərəf) məntiqini icra etməyə imkan verir. Gəlin servlet-in nə olduğunu və necə işlədiyini daha ətraflı izah edək:


### **Servlet nədir?**


- **Server Tərəfli Proqram**:

  - Servlet, server tərəfdə işləyən və istifadəçilərdən gələn istəkləri qəbul edib onlara cavab verən bir Java sinfidir. Məsələn, istifadəçi veb səhifədə bir düyməyə basdıqda və ya bir form doldurub göndərdikdə, servlet bu istəyi qəbul edib emal edə bilər.


- **Veb Tətbiqlərinin Dinamik Məzmun Yaratması**:

  - Servlet-lər dinamik məzmun (məsələn, məlumat bazasından məlumatların alınması, istifadəçi girişlərinin yoxlanılması, hesablama əməliyyatları və s.) yaratmaq üçün istifadə olunur və nəticəni HTML, JSON və ya XML formatında istifadəçiyə göndərə bilir.


### **Servlet necə işləyir?**


1. **İstək Göndərilməsi**:

   - İstifadəçi brauzerdən bir URL-ə müraciət edir və ya formu göndərir. Bu zaman serverə HTTP istəyi göndərilir.


2. **Server İstəyi Qəbul Edir**:

   - Server (məsələn, Tomcat kimi bir servlet konteyneri) bu istəyi qəbul edir və müvafiq servlet-ə yönləndirir.


3. **Servlet-in Emalı**:

   - Servlet, bu istəyi emal edir. Məsələn, istifadəçi məlumatlarını yoxlayır, məlumat bazasından məlumat çəkir və ya bəzi məntiqi əməliyyatlar aparır.


4. **Cavabın Yaradılması**:

   - Servlet, emalın nəticələrini HTML, JSON və ya digər formatda cavab kimi hazırlayır və bu cavabı server vasitəsilə istifadəçiyə göndərir.


### **Servlet-lərin İstifadə Məqsədləri**


- Dinamik veb məzmun yaratmaq (məsələn, bir onlayn mağazanın məhsul siyahısı).

- İstifadəçi girişlərini emal etmək və doğrulamaq.

- Məlumat bazasına müraciət edərək nəticələri göstərmək.

- Digər server tərəfli funksiyaları yerinə yetirmək.


### **Nümunə**


Məsələn, bir istifadəçi bir veb səhifədə login (giriş) formasını doldurur və göndərir. Bu zaman servlet həmin istifadəçinin məlumatlarını qəbul edir, məlumat bazasında bu məlumatların düzgünlüyünü yoxlayır və nəticəyə uyğun olaraq istifadəçiyə cavab verir.


Qısaca, **Servlet**, veb serverdə işləyən və istifadəçilərdən gələn istəkləri qəbul edərək emal edən bir Java proqramıdır. Veb tətbiqlərinin dinamik və interaktiv olmasına imkan verir.





### **Spring Security Authentication Flow**


1. **User Entered Credentials**: 

   - The process begins when the user enters their credentials (username and password) on the login form.


2. **Spring Security Filters**: 

   - These filters act as the entry point to handle the authentication process. The most crucial filter here is `UsernamePasswordAuthenticationFilter` which captures the credentials and sends them to the `AuthenticationManager` for validation.


3. **Authentication Manager**:

   - This manager orchestrates the authentication process. It doesn’t authenticate the user itself but delegates the job to one or more `AuthenticationProviders`.


4. **Authentication Providers**: 

   - These are responsible for the actual authentication logic. The most common one is `DaoAuthenticationProvider`, which works with a `UserDetailsService` to retrieve user details from the database or any other source.


5. **UserDetailsService**: 

   - This service loads the user details based on the provided username. It interacts with the data source (e.g., database) to fetch user information.


6. **Password Encoder**: 

   - After retrieving the user’s details, Spring Security compares the provided password with the stored password. The `PasswordEncoder` helps in encoding the raw password and comparing it with the stored (encoded) password.


7. **Authentication Result**: 

   - If the credentials are valid, the `Authentication` object is marked as authenticated (`isAuthenticated=true`), and the user is considered successfully authenticated.


8. **Returning to Authentication Manager**: 

   - The authenticated result is sent back through the `AuthenticationManager`.


9. **Security Context**: 

   - Once authentication is successful, the `Authentication` object is stored in the `SecurityContext`. This context holds the authenticated user's details for the duration of the session.


10. **Access Granted**: 

   - Finally, if everything is successful, the user gains access to the requested resources.


### **Summary:**

- The user provides credentials.

- Spring Security filters intercept the request.

- The `AuthenticationManager` delegates authentication to `AuthenticationProvider`.

- `UserDetailsService` fetches user details, and the `PasswordEncoder` verifies the password.

- If authentication succeeds, the `SecurityContext` holds the authenticated user's information.


This flow represents a typical Spring Security authentication process in the simplest way! If you have any questions or need further details, feel free to ask.




SpringSecurityFilter:

The very first responsibility of SpringSecurityFilters is to convert credentials from the HttpServletRequest object to Authentication object. Authentication object first isAuth = false


AuthenticationManager: 

It is going to take responsibility of completing the authentication and conveying the result back to the filters whether the authentication is successful or not. AuthenticationManger is only going to take the responsibility of completing the authentication, but it is not going to do the actual authentication. 


AuthenticationProvider: 

Very first activity AuthenticationProvider has to do is it has to load the user details based upon the username result. So to load user details it is going to take help from the UserDetailsManager or UserDetailsService implementation classes. So once the user details are loaded, the user details will be sent back to the AuthenticationProvider. Once the PasswordEncoder says that, okay, the passwords are matching accordingly, the AuthenticationProvider conveys back to the AuthenticationManager saying that, the authentication is successful. So how it is going to convey that? This time inside the response the Authentication object, it is going to have boolean value which is isAuthenticated as true. So based upon this value my AuthenticationManager know whether the authentication is successful or not. The same Authentication object will send back to SecurityFilters so filters know whether the authentication successful or not. Regardless of whether the authentication is successful or not, they are going to store the Authentication details is a SecurityContext. So they will store these authentication object against to a sessionId which is created for a given browser. So if the user is trying to access the same protected page from the same browser based upon the given sessionId the SpringSecurityFilters going to load the authentication object details from the SecurityContext and accordingly they are going to show either successful message or a error message. So this should also give a confirmation to you all the actual authentication execution is only going to happen for the very first request. Because there is no entry for a given sessionId inside the SecurityContext. Once the first request is processed and there is entry inside the SecurityContext for a sessionId, from next time onwards the SecurityFilters are not going to invoke AuthenticationManager. Instead they are going to leverage the details present inside the SecurityContext to send the successful response or to send the error response. 





First step: Ferz edekki biz hec bir konfquryasiyasiz Spring Boot Security proyekti yazmiwiq. Sorgu ilk olaraq AuthorizationFilter klasinin doFilter() metoduna daxil olur, sonra DefaultLoginPageGeneratingFilter klasinin doFilter() metoduna gedirl. 




-----------------------------

Demeli her wey SpringBootWebSecurityConfiguration 

 bu hisseden bashlayir. Burada defaultSecurityFilterChain

metod var. 

Yes, when your Spring Boot application starts, the SecurityFilterChain bean is created and initialized, which involves setting up the security filters. This process activates the filters even before any request is sent to the application. That's why your breakpoint on line 15 is triggered during application startup in debug mode. This initialization is part of how Spring Security sets up its filter chain to be ready for handling incoming requests.

package com.eazybytes.springsecuritysection2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
public class ProjectSecurityConfig {

@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
http.formLogin(withDefaults());
http.httpBasic(withDefaults());
return http.build();
}

}




Sonra sorgu BasicAuthenticationFilter klasinin doFilterInternal() metoduna daxil olur:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
Authentication authRequest = this.authenticationConverter.convert(request);
if (authRequest == null) {
this.logger.trace("Did not process authentication request since failed to find "
+ "username and password in Basic Authorization header");
chain.doFilter(request, response);
return;
}
String username = authRequest.getName();
this.logger.trace(LogMessage.format("Found username '%s' in Basic Authorization header", username));
if (authenticationIsRequired(username)) {
Authentication authResult = this.authenticationManager.authenticate(authRequest);
SecurityContext context = this.securityContextHolderStrategy.createEmptyContext();
context.setAuthentication(authResult);
this.securityContextHolderStrategy.setContext(context);
if (this.logger.isDebugEnabled()) {
this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", authResult));
}
this.rememberMeServices.loginSuccess(request, response, authResult);
this.securityContextRepository.saveContext(context, request, response);
onSuccessfulAuthentication(request, response, authResult);
}
}
catch (AuthenticationException ex) {
this.securityContextHolderStrategy.clearContext();
this.logger.debug("Failed to process authentication request", ex);
this.rememberMeServices.loginFail(request, response);
onUnsuccessfulAuthentication(request, response, ex);
if (this.ignoreFailure) {
chain.doFilter(request, response);
}
else {
this.authenticationEntryPoint.commence(request, response, ex);
}
return;
}

chain.doFilter(request, response);
}









































































Комментарии

Популярные сообщения из этого блога

Lesson1: JDK, JVM, JRE

SE_21_Lesson_11: Inheritance, Polymorphism

SE_21_Lesson_9: Initialization Blocks, Wrapper types, String class