Spring Security 5 Rol Tabanlı Yetkilendirme: Kapsamlı Rehber ve Örnekler

Spring Security 5 Rol Tabanlı Yetkilendirme: Kapsamlı Rehber ve Örnekler
Spring Security 5 ile rollere göre yetkilendirme işlemlerini adım adım gerçekleştirelim. Bu süreci uygulamalı olarak göstereceğim. Öncelikle bir Spring Boot projesi oluşturacağız, ardından gerekli bağımlılıkları ekleyecek, veritabanı tablolarını oluşturacak, örnek veriler ekleyecek ve kodları yazacağız.


1. Proje Oluşturma

Spring Initializr kullanarak yeni bir Spring Boot projesi oluşturun. Aşağıdaki bağımlılıkları ekleyin:

  • Spring Web
  • Spring Security
  • Spring Data JPA
  • H2 Database (veya tercihinize göre başka bir veritabanı)

2. Maven Bağımlılıkları

Proje oluşturulduktan sonra pom.xml dosyasına gerekli bağımlılıkları ekleyin:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> </dependencies>

3. Veritabanı Tabloları

Kullanıcılar ve rolleri için veritabanı tablolarını tanımlayalım. Örnek olarak H2 veritabanını kullanacağız. application.properties dosyasına aşağıdaki satırları ekleyin:

properties
spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=update

4. Entity Sınıfları

Kullanıcılar ve rolleri için entity sınıflarını oluşturalım.

Kullanıcı Entity

import javax.persistence.*; import java.util.Set; @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; private boolean enabled; @ManyToMany(fetch = FetchType.EAGER) @JoinTable( name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Set<Role> roles; // Getters and Setters }

Rol Entity

import javax.persistence.*; import java.util.Set; @Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToMany(mappedBy = "roles") private Set<User> users; // Getters and Setters }

5. Repository Sınıfları

Kullanıcı ve rol repository sınıflarını oluşturalım.

UserRepository

import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository<User, Long> { User findByUsername(String username); }

RoleRepository

import org.springframework.data.jpa.repository.JpaRepository; public interface RoleRepository extends JpaRepository<Role, Long> { }

6. Kullanıcı Detayları Servisi

Spring Security kullanıcı detayları servisini uygulayalım.

import org.springframework.beans.factory.annotation.Autowired; 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 MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found"); } return new org.springframework.security.core.userdetails
.User(user.getUsername(), user.getPassword()
, user.isEnabled(), true, true, true, user.getAuthorities()); } }

7. Güvenlik Yapılandırması

Spring Security yapılandırma sınıfını oluşturun.

java
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication
.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.
EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.
WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder
(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasRole("USER") .anyRequest().authenticated() .and() .formLogin().permitAll() .and() .logout().permitAll(); } }

8. Örnek Veriler

Uygulamanın başlangıcında örnek veriler ekleyelim.

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import java.util.HashSet; import java.util.Set; @Component public class DataLoader implements CommandLineRunner { @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired private PasswordEncoder passwordEncoder; @Override public void run(String... args) throws Exception { Role adminRole = new Role(); adminRole.setName("ROLE_ADMIN"); roleRepository.save(adminRole); Role userRole = new Role(); userRole.setName("ROLE_USER"); roleRepository.save(userRole); User admin = new User(); admin.setUsername("admin"); admin.setPassword(passwordEncoder.encode("admin")); admin.setEnabled(true); Set<Role> adminRoles = new HashSet<>(); adminRoles.add(adminRole); admin.setRoles(adminRoles); userRepository.save(admin); User user = new User(); user.setUsername("user"); user.setPassword(passwordEncoder.encode("user")); user.setEnabled(true); Set<Role> userRoles = new HashSet<>(); userRoles.add(userRole); user.setRoles(userRoles); userRepository.save(user); } }

9. Test Senaryosu

Uygulamayı çalıştırın ve farklı rollerle giriş yaparak yetkilendirme işlemlerini test edin.

  • /admin/** yolları sadece ROLE_ADMIN rolüne sahip kullanıcılar tarafından erişilebilir olacak.
  • /user/** yolları sadece ROLE_USER rolüne sahip kullanıcılar tarafından erişilebilir olacak.

Örnek Deneme

Projeyi çalıştırdıktan sonra, tarayıcıda aşağıdaki URL'leri deneyin:

  • /admin yoluna gitmek için admin kullanıcı adı ve admin şifresi ile giriş yapın.
  • /user yoluna gitmek için user kullanıcı adı ve user şifresi ile giriş yapın.

Bu adımları takip ederek Spring Security 5 ile rollere göre yetkilendirme işlemlerini gerçekleştirmiş olacaksını

Anatasyonlarla enpointlerin rollere göre yetkilendirilmesiSpring Security ile endpoint'leri rollere göre yetkilendirmenin bir diğer yolu, method seviyesinde anotasyonlar kullanmaktır. Bu yöntemde, belirli rollerin belirli endpoint'lere erişimini kontrol etmek

 için @PreAuthorize veya @Secured anotasyonlarını kullanabilirsiniz.

Proje Ayarları

Önceki örnekte kullanılan yapılandırma, entity sınıfları ve repository sınıfları bu örnek için de geçerlidir. Bu nedenle, direkt olarak anotasyon kullanarak nasıl yetkilendirme yapacağımızı gösteren adımlara geçelim.

1. Güvenlik Yapılandırması

Anotasyonlarla yetkilendirme kullanabilmek için, Spring Security yapılandırma sınıfımızı buna göre güncellememiz gerekiyor.


import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders
.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration
.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration
.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.
WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder
(passwordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().permitAll() .and() .logout().permitAll(); } }

2. Controller Sınıfı

Controller sınıfında, endpoint'leri rollere göre yetkilendirmek için anotasyonları kullanabiliriz.


import org.springframework.security.access.annotation.Secured; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api") public class MyController { @GetMapping("/admin") @PreAuthorize("hasRole('ROLE_ADMIN')") public String adminEndpoint() { return "Admin content"; } @GetMapping("/user") @PreAuthorize("hasRole('ROLE_USER')") public String userEndpoint() { return "User content"; } @GetMapping("/common") @Secured({"ROLE_USER", "ROLE_ADMIN"}) public String commonEndpoint() { return "Common content for both USER and ADMIN"; } }

3. Örnek Veriler

Önceki örnekte oluşturduğumuz DataLoader sınıfı bu örnek için de geçerlidir. Örnek verileri eklemeyi unutmayın.

4. Test Senaryosu

Uygulamayı çalıştırın ve farklı rollerle giriş yaparak yetkilendirme işlemlerini test edin.

  • /api/admin endpoint'ine sadece ROLE_ADMIN rolüne sahip kullanıcılar erişebilir.
  • /api/user endpoint'ine sadece ROLE_USER rolüne sahip kullanıcılar erişebilir.
  • /api/common endpoint'ine hem ROLE_USER hem de ROLE_ADMIN rolüne sahip kullanıcılar erişebilir.

Sonuç

Bu adımları takip ederek, Spring Security ile anotasyonları kullanarak endpoint'lerin rollere göre yetkilendirilmesini sağlamış olursunuz. Bu yöntem, kodunuzu daha okunabilir ve yönetilebilir hale getirir.

Hiç yorum yok

Rastgele İçerik

© tüm hakları saklıdır
made with by templateszoo