Spring Security - Spring Boot’da authentication, authorization va umumiy web xavfsizlikni boshqaradigan asosiy framework. Bu bo‘lim ichida quyidagilar bor: SecurityFilterChain, HTTP Basic, Form Login, UserDetailsService, UserDetails, PasswordEncoder, BCrypt, role-based access, @PreAuthorize, CSRF.
Spring Security’ning asosiy vazifasi: kim kiryapti va unga nima qilish mumkin degan savollarga javob berish. Rasmiy hujjatlarda ham Spring Security authentication, authorization va common attacks’dan himoya qilish framework’i sifatida tariflanadi. (Home)
1. Authentication va Authorization farqi
Spring Security’ni tushunish uchun avval ikki so‘zni ajratib olish kerak.
Authentication
Authentication - user kimligini aniqlash.
Savol:
Siz kimsiz?Misollar:
Login + password
JWT token
Session cookie
OAuth2 / Google loginMasalan:
ali@mail.com + passwordto‘g‘ri bo‘lsa, tizim userni tanidi.
Authorization
Authorization - userga nima qilishga ruxsat borligini tekshirish.
Savol:
Sizga bunga ruxsat bormi?Misollar:
ADMIN product delete qila oladi
USER faqat product ko‘ra oladi
MANAGER order status o‘zgartira oladiOddiy farq
Authentication → kimligini tekshirish
Authorization → huquqini tekshirishMasalan:
User login qildi → authentication
User admin panelga kirmoqchi → authorization2. Spring Security qo‘shilganda nima bo‘ladi?
Agar projectga dependency qo‘shsangiz:
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>Gradle
implementation 'org.springframework.boot:spring-boot-starter-security'Spring Boot avtomatik security yoqadi.
Default holatda ko‘p endpointlar login talab qiladi. Spring Security hujjatlarida ham HttpSecurity ishlatilganda authorization qoidalarini e’lon qilish kerakligi va default holatda requestlar authenticated bo‘lishi aytiladi. (Home)
3. SecurityFilterChain nima?
SecurityFilterChain - request security filtrlaridan qanday o‘tishini belgilaydigan konfiguratsiya.
Rasmiy hujjatga ko‘ra, SecurityFilterChain joriy request uchun qaysi Spring Security filterlari ishlashini aniqlashda ishlatiladi. (Home)
Oddiy flow:
Client request
↓
Spring Security Filters
↓
Authentication tekshiruvi
↓
Authorization tekshiruvi
↓
ControllerMasalan request:
GET /api/productsSpring Security tekshiradi:
Bu endpoint ochiqmi?
Login kerakmi?
User login qilganmi?
Role yetarlimi?4. Eng oddiy Security config
Spring Security 6+ uslubida SecurityFilterChain bean yoziladi.
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;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.httpBasic(basic -> {})
.build();
}
}Bu konfiguratsiya ma’nosi:
/api/public/** → hamma kira oladi
qolgan hamma endpoint → login talab qiladi
httpBasic → Basic Auth yoqiladi5. HTTP Basic nima?
HTTP Basic - eng oddiy authentication turi.
Client har requestda username/password yuboradi.
Masalan Postman’da:
Authorization → Basic Auth
Username: user
Password: passwordHTTP header taxminan shunday bo‘ladi:
Authorization: Basic dXNlcjpwYXNzd29yZA==Bu production uchun ideal emas, lekin boshlang'ich bosqichda Spring Security’ni tushunish uchun juda qulay.
6. In-memory user bilan boshlash
Avval database ishlatmasdan user yaratamiz.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class UserConfig {
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder.encode("12345"))
.roles("ADMIN")
.build();
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder.encode("12345"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(admin, user);
}
}Bu yerda ikkita user bor:
admin / 12345 → ADMIN
user / 12345 → USER7. PasswordEncoder nima?
Passwordni hech qachon plain text saqlamaslik kerak.
Yomon:
password = 12345Yaxshi:
password = $2a$10$...PasswordEncoder passwordni hash qiladi va login vaqtida tekshiradi. Spring Security API hujjatlarida PasswordEncoder password encoding uchun service interface ekani, BCryptPasswordEncoder esa preferred implementation ekani ko‘rsatilgan. (Home)
BCrypt ishlatish
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class PasswordConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}BCrypt passwordlarni hash qilish uchun keng ishlatiladi; rasmiy hujjatda BCrypt ataylab sekin ishlashi, bu password cracking’ni qiyinlashtirishi aytiladi. (Home)
8. Role-based access
Endi endpointlarni role bo‘yicha himoya qilamiz.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/products/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.httpBasic(basic -> {})
.build();
}
}Ma’nosi:
/api/public/** → hamma uchun ochiq
/api/admin/** → faqat ADMIN
/api/products/** → USER yoki ADMIN
qolganlari → login kerakRole nomida muhim qoida
Siz user yaratganda:
.roles("ADMIN")deb yozasiz.
Security config’da:
.hasRole("ADMIN")deb yozasiz.
Lekin ichkarida Spring buni:
ROLE_ADMINsifatida saqlaydi.
Shuning uchun bunday yozmang:
.roles("ROLE_ADMIN") // noto‘g‘ri bo‘lishi mumkinTo‘g‘risi:
.roles("ADMIN")9. hasRole va hasAuthority farqi
hasRole
.requestMatchers("/api/admin/**").hasRole("ADMIN")Bu ichkarida ROLE_ADMIN authority’ni qidiradi.
hasAuthority
.requestMatchers("/api/admin/**").hasAuthority("ADMIN")Bu aniq ADMIN authority’ni qidiradi.
Agar siz authority’ni ROLE_ADMIN deb saqlagan bo‘lsangiz:
.hasAuthority("ROLE_ADMIN")ishlatiladi.
Java developer uchun oddiy qoida:
roles("ADMIN") ishlatsangiz → hasRole("ADMIN")
authorities("product:delete") ishlatsangiz → hasAuthority("product:delete")10. Test controller
@RestController
@RequestMapping("/api")
public class TestController {
@GetMapping("/public/hello")
public String publicHello() {
return "Public endpoint";
}
@GetMapping("/products")
public String products() {
return "Products endpoint";
}
@GetMapping("/admin/dashboard")
public String admin() {
return "Admin endpoint";
}
}Tekshirish:
GET /api/public/hello → login kerak emas
GET /api/products → USER yoki ADMIN kerak
GET /api/admin/dashboard → ADMIN kerak11. UserDetails nima?
UserDetails - Spring Security user haqida bilishi kerak bo‘lgan ma’lumotlar modeli.
Unda odatda quyidagilar bor:
username
password
authorities / roles
account expired emasmi
account locked emasmi
credentials expired emasmi
enabledmiIn-memory userda Spring’ning tayyor User classidan foydalandik:
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder.encode("12345"))
.roles("USER")
.build();Real loyihada esa user database’dan keladi.
12. UserDetailsService nima?
UserDetailsService - username bo‘yicha userni topib beradi.
Asosiy method:
UserDetails loadUserByUsername(String username);Spring Security login vaqtida shu methodni chaqiradi.
Flow:
Client username/password yuboradi
↓
Spring Security username bo‘yicha userni qidiradi
↓
UserDetailsService.loadUserByUsername()
↓
Database’dan user topiladi
↓
PasswordEncoder passwordni solishtiradi
↓
Login success yoki fail13. Database bilan UserDetailsService
Masalan AppUser entity:
@Entity
@Table(name = "users")
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String role;
private boolean enabled = true;
// getters/setters
}Repository:
public interface AppUserRepository extends JpaRepository<AppUser, Long> {
Optional<AppUser> findByUsername(String username);
}Custom UserDetailsService:
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final AppUserRepository appUserRepository;
public CustomUserDetailsService(AppUserRepository appUserRepository) {
this.appUserRepository = appUserRepository;
}
@Override
public UserDetails loadUserByUsername(String username) {
AppUser appUser = appUserRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User topilmadi"));
return User.builder()
.username(appUser.getUsername())
.password(appUser.getPassword())
.roles(appUser.getRole())
.disabled(!appUser.isEnabled())
.build();
}
}Agar database’da:
username = admin
password = BCrypt hash
role = ADMINbo‘lsa, login ishlaydi.
14. User register qilishda password hash qilish
Yomon:
user.setPassword(request.password());Bu passwordni plain text saqlaydi.
To‘g‘ri:
user.setPassword(passwordEncoder.encode(request.password()));Misol:
@Service
public class AuthService {
private final AppUserRepository appUserRepository;
private final PasswordEncoder passwordEncoder;
public AuthService(AppUserRepository appUserRepository,
PasswordEncoder passwordEncoder) {
this.appUserRepository = appUserRepository;
this.passwordEncoder = passwordEncoder;
}
@Transactional
public void register(RegisterRequest request) {
if (appUserRepository.findByUsername(request.username()).isPresent()) {
throw new BadRequestException("Username allaqachon mavjud");
}
AppUser user = new AppUser();
user.setUsername(request.username());
user.setPassword(passwordEncoder.encode(request.password()));
user.setRole("USER");
user.setEnabled(true);
appUserRepository.save(user);
}
}15. Form Login nima?
formLogin - browser applicationlarda ishlatiladigan login form.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.formLogin(form -> {})
.build();
}Bu holatda Spring default login page beradi.
Web MVC, Thymeleaf, server-rendered app uchun qulay.
Lekin REST API uchun ko‘pincha:
HTTP Basic
JWT
OAuth2 Resource Serverishlatiladi.
Boshlang'ich bosqichda avval httpBasic va role-based access tushunib olish yaxshi.
16. REST API uchun CSRF
CSRF - Cross-Site Request Forgery. Bu active session/cookie ishlatiladigan web applarda muhim hujum turi.
Spring Security CSRF himoyani default yoqadi va unsafe HTTP methodlar, masalan POST, uchun himoya qiladi. (Home)
REST API’da ko‘p holatda token-based auth, masalan JWT, ishlatilsa va session cookie ishlatilmasa, CSRF disable qilinadi:
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.httpBasic(basic -> {})
.build();
}Lekin muhim:
Cookie/session bilan browser login ishlatsangiz → CSRF kerak bo‘lishi mumkin
JWT Bearer token bilan stateless REST API bo‘lsa → ko‘pincha CSRF disable qilinadi17. Stateless REST API konfiguratsiyasi
REST API’da session ishlatmaslik uchun:
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.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(basic -> {})
.build();
}
}Bu yerda:
csrf disable → REST token/basic auth uchun soddalashtirish
STATELESS → server session saqlamaydi
/api/auth/** → register/login uchun ochiq
/api/admin/** → ADMIN kerak
anyRequest → login kerak18. @PreAuthorize nima?
@PreAuthorize - method level security.
Ya’ni endpoint yoki service method ustida ruxsat tekshirish.
Spring Security method-level authorization’ni annotationlar orqali yoqishini rasmiy hujjat ko‘rsatadi. (Home)
Avval yoqamiz:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig {
}Keyin ishlatamiz:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
productService.delete(id);
}
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
@GetMapping
public List<ProductResponse> getAll() {
return productService.getAll();
}
}@PreAuthorize service’da ishlatish
Ko‘pincha service layer’da qo‘yish ham foydali:
@Service
public class ProductService {
@PreAuthorize("hasRole('ADMIN')")
@Transactional
public void delete(Long id) {
// delete logic
}
}Nega service’da yaxshi?
Chunki boshqa controller yoki internal method ham shu service’ni chaqirsa, security qoida saqlanadi.
19. Endpoint security vs method security
Endpoint security
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/admin/**").hasRole("ADMIN")
)Bu URL darajasida tekshiradi.
Method security
@PreAuthorize("hasRole('ADMIN')")
public void delete(Long id) {}Bu method darajasida tekshiradi.
Amaliy qoida:
URL bo‘yicha umumiy qoida → SecurityFilterChain
Nozik biznes qoida → @PreAuthorize20. Security uchun response statuslar
Spring Security’da eng ko‘p uchraydigan statuslar:
Holat | Status | Ma’no |
|---|---|---|
Login qilmagan |
| Authentication yo‘q |
Login qilgan, lekin ruxsat yo‘q |
| Authorization yetarli emas |
Endpoint ochiq |
| Ruxsat bor |
Masalan:
GET /api/admin/dashboardAgar user login qilmagan bo‘lsa:
401 UnauthorizedAgar USER roli bilan kirsa:
403 ForbiddenAgar ADMIN roli bilan kirsa:
200 OK21. To‘liq minimal config
Bu Java developer uchun yaxshi boshlang‘ich config:
package com.example.demo.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/products/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.httpBasic(basic -> {})
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}22. Product API uchun security
Endpointlar:
POST /api/auth/register
GET /api/products
GET /api/products/{id}
POST /api/products
PUT /api/products/{id}
DELETE /api/products/{id}Security qoida:
/api/auth/** → public
GET /api/products → USER yoki ADMIN
POST /api/products → ADMIN
PUT /api/products → ADMIN
DELETE /api/products → ADMINConfig:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/products/**")
.hasAnyRole("USER", "ADMIN")
.requestMatchers(HttpMethod.POST, "/api/products/**")
.hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/products/**")
.hasRole("ADMIN")
.requestMatchers(HttpMethod.DELETE, "/api/products/**")
.hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(basic -> {})
.build();
}Import kerak:
import org.springframework.http.HttpMethod;23. Register request validation
public record RegisterRequest(
@NotBlank(message = "Username majburiy")
@Size(min = 3, max = 50, message = "Username 3 dan 50 tagacha bo‘lishi kerak")
String username,
@NotBlank(message = "Password majburiy")
@Size(min = 6, max = 100, message = "Password kamida 6 belgi bo‘lishi kerak")
String password
) {
}Controller:
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private final AuthService authService;
public AuthController(AuthService authService) {
this.authService = authService;
}
@PostMapping("/register")
public void register(@Valid @RequestBody RegisterRequest request) {
authService.register(request);
}
}24. Passwordni response’da qaytarmang
Yomon:
public record UserResponse(
Long id,
String username,
String password,
String role
) {
}To‘g‘ri:
public record UserResponse(
Long id,
String username,
String role
) {
}Password hech qachon API response’da qaytmasin:
Plain password → mutlaqo yo‘q
Hash password → response’da kerak emas25. Security bilan exception handling
Spring Security xatolari ba’zan sizning GlobalExceptionHandlerga tushmaydi, chunki ular filter chain ichida yuz beradi.
Masalan:
401 Unauthorized
403 ForbiddenUlarni customize qilish uchun:
.exceptionHandling(ex -> ex
.authenticationEntryPoint((request, response, authException) -> {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("""
{"code":"UNAUTHORIZED","message":"Login talab qilinadi"}
""");
})
.accessDeniedHandler((request, response, accessDeniedException) -> {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType("application/json");
response.getWriter().write("""
{"code":"FORBIDDEN","message":"Ruxsat yo‘q"}
""");
})
)To‘liq config ichida:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(ex -> ex
.authenticationEntryPoint((request, response, authException) -> {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("""
{"code":"UNAUTHORIZED","message":"Login talab qilinadi"}
""");
})
.accessDeniedHandler((request, response, accessDeniedException) -> {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType("application/json");
response.getWriter().write("""
{"code":"FORBIDDEN","message":"Ruxsat yo‘q"}
""");
})
)
.httpBasic(basic -> {})
.build();
}Import:
import jakarta.servlet.http.HttpServletResponse;26. Ko‘p uchraydigan xatolar
Xato 1: Passwordni plain text saqlash
Yomon:
user.setPassword(request.password());To‘g‘ri:
user.setPassword(passwordEncoder.encode(request.password()));Xato 2: hasRole("ROLE_ADMIN") yozish
Yomon:
.hasRole("ROLE_ADMIN")To‘g‘ri:
.hasRole("ADMIN")Xato 3: Hamma endpointni public qilib qo‘yish
Yomon:
.anyRequest().permitAll()Bu test uchun qulay, lekin real API’da xavfli.
Yaxshi:
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()Xato 4: CSRFni tushunmasdan disable qilish
REST API’da disable qilish ko‘p uchraydi, lekin browser session/cookie ishlatiladigan app’da CSRF himoya kerak bo‘lishi mumkin.
Xato 5: Role va business logicni aralashtirish
Yomon:
if (user.getRole().equals("ADMIN")) {
// controller ichida qo‘lda tekshirish
}Yaxshiroq:
@PreAuthorize("hasRole('ADMIN')")yoki SecurityFilterChain.
Xato 6: Passwordni logga chiqarish
Yomon:
log.info("User password: {}", request.password());Mutlaqo qilinmaydi.
27. Boshlang'ich Java developer uchun eng muhim flow
Client request yuboradi
↓
SecurityFilterChain requestni ushlaydi
↓
Endpoint publicmi yoki protectedmi tekshiradi
↓
Agar protected bo‘lsa, authentication tekshiradi
↓
UserDetailsService userni topadi
↓
PasswordEncoder passwordni solishtiradi
↓
Role/authority tekshiriladi
↓
Controllerga o‘tadi yoki 401/403 qaytadi28. Product API uchun amaliy vazifa
Oldingi Product CRUD API loyihasiga Spring Security qo‘shing.
Talablar
Dependency:
spring-boot-starter-securityUser entity:
id
username
password
role
enabledEndpointlar:
POST /api/auth/register → public
GET /api/products/** → USER yoki ADMIN
POST /api/products/** → ADMIN
PUT /api/products/** → ADMIN
DELETE /api/products/** → ADMINClasslar:
common.config.SecurityConfig
auth.AuthController
auth.AuthService
user.AppUser
user.AppUserRepository
user.CustomUserDetailsServiceMajburiy qoidalar:
Password BCrypt bilan hash qilinsin
Password response’da qaytmasin
SecurityFilterChain ishlatilsin
@EnableMethodSecurity qo‘shilsin
@PreAuthorize bilan delete method ADMINga cheklansin
CSRF REST API uchun disable qilinsin
SessionCreationPolicy.STATELESS bo‘lsinXulosa
Spring Security basics uchun Java developer quyidagilarni bilishi kerak:
Authentication vs Authorization
SecurityFilterChain
HTTP Basic
Form Login
UserDetails
UserDetailsService
PasswordEncoder
BCryptPasswordEncoder
Role-based access
hasRole vs hasAuthority
@PreAuthorize
@EnableMethodSecurity
CSRF nima va qachon disable qilinadi
401 vs 403Eng muhim qoida:
Password plain text saqlanmaydi.
Endpointlar default protected bo‘lsin.
Faqat kerakli public endpointlar ochilsin.
Role tekshiruvlari SecurityFilterChain yoki @PreAuthorize orqali qilinsin.