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:
propertiesspring.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.
javaimport 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ı sadeceROLE_ADMIN
rolüne sahip kullanıcılar tarafından erişilebilir olacak./user/**
yolları sadeceROLE_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çinadmin
kullanıcı adı veadmin
şifresi ile giriş yapın./user
yoluna gitmek içinuser
kullanıcı adı veuser
ş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ı
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 sadeceROLE_ADMIN
rolüne sahip kullanıcılar erişebilir./api/user
endpoint'ine sadeceROLE_USER
rolüne sahip kullanıcılar erişebilir./api/common
endpoint'ine hemROLE_USER
hem deROLE_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.