Spring Security Basics

01.07.2026 | Muallif: Jaxongir a.k.a | Kategoriya: Spring Boot | 22 daqiqa o'qish

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 login

Masalan:

ali@mail.com + password

to‘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 oladi

Oddiy farq

Authentication → kimligini tekshirish
Authorization  → huquqini tekshirish

Masalan:

User login qildi → authentication
User admin panelga kirmoqchi → authorization

2. 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
     ↓
Controller

Masalan request:

GET /api/products

Spring 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 yoqiladi

5. HTTP Basic nima?

HTTP Basic - eng oddiy authentication turi.

Client har requestda username/password yuboradi.

Masalan Postman’da:

Authorization → Basic Auth
Username: user
Password: password

HTTP 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  → USER

7. PasswordEncoder nima?

Passwordni hech qachon plain text saqlamaslik kerak.

Yomon:

password = 12345

Yaxshi:

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 kerak

Role nomida muhim qoida

Siz user yaratganda:

.roles("ADMIN")

deb yozasiz.

Security config’da:

.hasRole("ADMIN")

deb yozasiz.

Lekin ichkarida Spring buni:

ROLE_ADMIN

sifatida saqlaydi.

Shuning uchun bunday yozmang:

.roles("ROLE_ADMIN") // noto‘g‘ri bo‘lishi mumkin

To‘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 kerak

11. 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
enabledmi

In-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 fail

13. 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 = ADMIN

bo‘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 Server

ishlatiladi.

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 qilinadi

17. 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 kerak

18. @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 → @PreAuthorize

20. Security uchun response statuslar

Spring Security’da eng ko‘p uchraydigan statuslar:

Holat

Status

Ma’no

Login qilmagan

401 Unauthorized

Authentication yo‘q

Login qilgan, lekin ruxsat yo‘q

403 Forbidden

Authorization yetarli emas

Endpoint ochiq

200 OK

Ruxsat bor

Masalan:

GET /api/admin/dashboard

Agar user login qilmagan bo‘lsa:

401 Unauthorized

Agar USER roli bilan kirsa:

403 Forbidden

Agar ADMIN roli bilan kirsa:

200 OK

21. 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 → ADMIN

Config:

@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 emas

25. Security bilan exception handling

Spring Security xatolari ba’zan sizning GlobalExceptionHandlerga tushmaydi, chunki ular filter chain ichida yuz beradi.

Masalan:

401 Unauthorized
403 Forbidden

Ularni 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 qaytadi

28. Product API uchun amaliy vazifa

Oldingi Product CRUD API loyihasiga Spring Security qo‘shing.

Talablar

Dependency:

spring-boot-starter-security

User entity:

id
username
password
role
enabled

Endpointlar:

POST /api/auth/register → public
GET /api/products/**    → USER yoki ADMIN
POST /api/products/**   → ADMIN
PUT /api/products/**    → ADMIN
DELETE /api/products/** → ADMIN

Classlar:

common.config.SecurityConfig
auth.AuthController
auth.AuthService
user.AppUser
user.AppUserRepository
user.CustomUserDetailsService

Majburiy 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‘lsin

Xulosa

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 403

Eng muhim qoida:

Password plain text saqlanmaydi.
Endpointlar default protected bo‘lsin.
Faqat kerakli public endpointlar ochilsin.
Role tekshiruvlari SecurityFilterChain yoki @PreAuthorize orqali qilinsin.