0Pricing
Spring Boot 4 Complete Guide · Ders

SpEL ve Özel Oylayıcılarla Metot Güvenliği

@PreAuthorize, SpEL ifadeleri ve özel yetkilendirme mantığıyla ayrıntılı erişim denetimi uygulayın.

SpEL ve Özel Oylayıcılarla Metot Güvenliği, CoddyKit'te ücretsiz bir Spring Boot 4 Complete Guide dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Spring Boot 4 Complete Guide öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Spring Boot 4 Complete Guide kursu toplamda 4 dersten oluşur.

Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.

Why Method Security?

URL-based security (HttpSecurity matchers) guards entry points, but it cannot see the arguments a method receives or the object it returns. Method security closes that gap by enforcing rules right at the service layer.

  • Defense in depth — protection survives even if a controller forgets a check.
  • Fine-grained — decide based on parameters, return values, and the authenticated principal.
  • Reusable — the same secured service can be called from REST, GraphQL, or a message listener and stays protected.

In this lesson we enforce access with @PreAuthorize, SpEL expressions, and a custom authorization manager.

Enabling Method Security

In Spring Boot 4 / Spring Security 6, method security is opt-in. Add @EnableMethodSecurity to a configuration class. It activates the annotations through an AOP proxy.

  • prePostEnabled defaults to true — @PreAuthorize and @PostAuthorize work out of the box.
  • Set securedEnabled = true for the legacy @Secured, or jsr250Enabled = true for @RolesAllowed.

Note: the old @EnableGlobalMethodSecurity is removed — always use @EnableMethodSecurity.

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;

@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig {
    // prePostEnabled = true by default
    // @PreAuthorize / @PostAuthorize now active
}

@PreAuthorize with Roles and Authorities

@PreAuthorize evaluates a SpEL expression before the method runs. If it returns false, Spring throws AccessDeniedException and the body never executes.

  • hasRole('ADMIN') — checks the ROLE_ADMIN authority (the prefix is added for you).
  • hasAuthority('SCOPE_orders:write') — exact authority match, no prefix added.
  • hasAnyRole('ADMIN','MANAGER') and the boolean operators and / or / !.
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class AccountService {

    @PreAuthorize("hasRole('ADMIN')")
    public void closeAccount(Long accountId) {
        // only ROLE_ADMIN reaches here
    }

    @PreAuthorize("hasAnyRole('ADMIN','SUPPORT') or hasAuthority('SCOPE_accounts:write')")
    public void freezeAccount(Long accountId) {
        // ...
    }
}

Referencing Method Arguments with #

The real power of SpEL is reading method arguments. Prefix a parameter name with # to use it inside the expression. This lets you compare the principal's identity to the data being acted on.

  • authentication — the current Authentication object.
  • principal — the principal (often a UserDetails or JWT).
  • #username, #order.ownerId — method arguments and their properties.

Argument names require parameters compiled with -parameters (Spring Boot enables this by default).

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class ProfileService {

    // A user may edit only their own profile, unless they are an admin
    @PreAuthorize("#username == authentication.name or hasRole('ADMIN')")
    public void updateProfile(String username, ProfileDto dto) {
        // ...
    }
}

@PostAuthorize and returnObject

@PostAuthorize runs after the method returns and can inspect the result via returnObject. Use it when you must load the entity first to know who owns it.

  • Good for “you can read this record only if it belongs to you.”
  • The method body does execute, so avoid it for operations with side effects you must prevent.
  • On denial, the return value is discarded and AccessDeniedException is thrown.
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.stereotype.Service;

@Service
public class DocumentService {

    @PostAuthorize("returnObject.ownerUsername == authentication.name or hasRole('ADMIN')")
    public Document findById(Long id) {
        return repository.findById(id).orElseThrow();
    }
}

@PreFilter and @PostFilter on Collections

Filtering annotations prune collections element by element instead of throwing. They use a special variable filterObject bound to each element.

  • @PreFilter — strips disallowed elements from a collection argument before the method runs.
  • @PostFilter — strips disallowed elements from the returned collection.
  • Use filterTarget when a method has more than one collection parameter.

Caution: post-filtering large result sets in memory can be costly — prefer filtering in the query when possible.

import org.springframework.security.access.prepost.PostFilter;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class OrderService {

    // Caller sees only the orders they own (admins see all)
    @PostFilter("filterObject.ownerUsername == authentication.name or hasRole('ADMIN')")
    public List<Order> findRecentOrders() {
        return repository.findRecent();
    }
}

Calling a Bean from SpEL with @

When logic gets complex, push it into a Spring bean and call it from the expression using @beanName.method(...). This keeps annotations readable and the rule unit-testable.

  • The @ resolves a bean from the application context.
  • Pass authentication and method arguments straight into the bean method.
  • The method must return a boolean.
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

@Component("projectAccess")
public class ProjectAccessEvaluator {

    public boolean canEdit(Authentication auth, Long projectId) {
        String user = auth.getName();
        return membershipRepository.isEditor(user, projectId);
    }
}

// Usage on a service method:
// @PreAuthorize("@projectAccess.canEdit(authentication, #projectId)")
// public void rename(Long projectId, String name) { ... }

PermissionEvaluator and hasPermission

SpEL exposes hasPermission(target, permission), which delegates to a PermissionEvaluator bean. It is the canonical hook for domain-object (ACL-style) authorization without inlining logic in every annotation.

  • hasPermission(#doc, 'WRITE') — passes the object and a permission key.
  • hasPermission(#id, 'com.app.Document', 'READ') — passes an id plus the type.
  • You register exactly one PermissionEvaluator via a MethodSecurityExpressionHandler.
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import java.io.Serializable;

public class DocumentPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication auth, Object target, Object permission) {
        if (target instanceof Document doc) {
            return "WRITE".equals(permission)
                ? doc.getOwnerUsername().equals(auth.getName())
                : true; // READ allowed for all in this example
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication auth, Serializable id,
                                 String type, Object permission) {
        return false; // resolve by id+type if needed
    }
}

Registering a Custom Expression Handler

To wire your PermissionEvaluator into SpEL, expose a DefaultMethodSecurityExpressionHandler bean and set the evaluator on it. Spring Security picks it up for all method annotations.

  • The bean name is not important; the type is.
  • You can also attach a custom RoleHierarchy here so hasRole respects inheritance.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;

@Configuration
@EnableMethodSecurity
public class ExpressionHandlerConfig {

    @Bean
    static DefaultMethodSecurityExpressionHandler expressionHandler() {
        var handler = new DefaultMethodSecurityExpressionHandler();
        handler.setPermissionEvaluator(new DocumentPermissionEvaluator());
        return handler;
    }
}

Custom AuthorizationManager (the New Voter)

Spring Security 6 replaced the legacy AccessDecisionVoter with the simpler AuthorizationManager<T>. For method security the type parameter is MethodInvocation. Implement check to return an AuthorizationDecision.

  • Return new AuthorizationDecision(true|false) — or null to abstain and let other managers decide.
  • Register it with @EnableMethodSecurity(prePostEnabled = false) plus an advisor, or combine managers with AuthorizationManagers.allOf(...).
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import java.util.function.Supplier;

public class BusinessHoursAuthorizationManager
        implements AuthorizationManager<MethodInvocation> {

    @Override
    public AuthorizationDecision check(Supplier<Authentication> auth,
                                       MethodInvocation invocation) {
        int hour = java.time.LocalTime.now().getHour();
        boolean withinHours = hour >= 9 && hour < 18;
        return new AuthorizationDecision(withinHours);
    }
}

Pre vs Post: Choosing Correctly

Picking the wrong annotation either leaks data or blocks valid calls. A quick decision guide:

  • Rule depends only on arguments + principal → @PreAuthorize (fast, no side effects).
  • Rule depends on the loaded entity's ownership → @PostAuthorize.
  • Trimming a collection per-element → @PostFilter (or filter in the query).
  • Reusable domain-object rule → hasPermission + PermissionEvaluator.

Remember: @PostAuthorize and @PostFilter run the method body, so never rely on them to stop a mutating operation.

Quick Check

You have a method Document findById(Long id) that loads a document, and access should be granted only if the returned document's ownerUsername equals the caller, or the caller is an admin. Which annotation expresses this correctly?

Recap

You now enforce fine-grained access at the method layer:

  • @EnableMethodSecurity turns on annotation-driven checks (no more @EnableGlobalMethodSecurity).
  • @PreAuthorize guards before execution using SpEL: hasRole, hasAuthority, #args, and authentication.
  • @PostAuthorize inspects returnObject; @PreFilter/@PostFilter prune collections via filterObject.
  • Push complex rules into a bean (@beanName.method(...)) or a PermissionEvaluator behind hasPermission.
  • For cross-cutting policy, implement AuthorizationManager<MethodInvocation> — the modern replacement for voters.

Rule of thumb: prefer pre-checks for speed and safety; reach for post-checks only when the decision needs the loaded data.

Sıkça Sorulan Sorular

“SpEL ve Özel Oylayıcılarla Metot Güvenliği” dersi ücretsiz mi?

Evet — “SpEL ve Özel Oylayıcılarla Metot Güvenliği” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Spring Boot 4 Complete Guide kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Spring Boot 4 Complete Guide kursu toplamda 4 dersten oluşur.

“SpEL ve Özel Oylayıcılarla Metot Güvenliği” dersinde ne öğreneceğim?

@PreAuthorize, SpEL ifadeleri ve özel yetkilendirme mantığıyla ayrıntılı erişim denetimi uygulayın. Spring Boot 4 Complete Guide ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Spring Boot 4 Complete Guide öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Spring Boot 4 Complete Guide, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“SpEL ve Özel Oylayıcılarla Metot Güvenliği” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Spring Boot 4 Complete Guide dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Spring Boot 4 Complete Guide dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Kaynak Sunucusu JWT Doğrulaması ve Talepler
  2. OAuth2 İstemcisi ve Yetkilendirme Kodu Akışı
  3. SpEL ve Özel Oylayıcılarla Metot Güvenliği
  4. Opak Belirteç İncelemesi ve Belirteç Değişimi
← Spring Boot 4 Complete Guide Sayfasına Dön