/blog/*

Spring Security JDBC Authentication

Pada tulisan sebelumnya kita sudah membahas secara garis besar bagaimana spring-security membatasi hak akses pada suatu user untuk dapat mengakses resources tertentu. Sudah sedikit dijelaskan juga bagaimana spring-security menangani proses autentikasi meskipun masih sangat basic.

Pada implementasi sesungguhnya semua data credential user akan disimpan dengan aman pada suatu database. Pada tulisan kali ini kita akan bahas bagaimana spring-security mengakses database untuk melakukan proses autentikasi.

Dependency dan JDBC Configuration

Sebagai contoh kasus disini kita akan menggunakan database PostgreSQL, oleh karena itu kita membutuhkan driver PosgreSQL pada project kita. Selain itu juga kita membutuhkan module sping-data-jpa untuk kebutuhan ORM.

Pada tulisan ini kita tidak membahas mengenai spring-data-jpa karena tulisan ini berfokus pada aspek spring-secity saja.

<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.12</version>
    </dependency>
</dependencies>

Untuk konfigurasi connectornya berikut contohnya.

spring.datasource.url=jdbc:postgresql://localhost:5432/spring_security_demo
spring.datasource.username=postgres
spring.datasource.password=secret

Selanjutnya kita buat class entity beserta repository sebagai mapping dari table yang ada didatabase.

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "username", nullable = false, unique = true)
    private String username;

    @Column(name="password", nullable = false)
    private String password;

    @Enumerated(EnumType.STRING)
    @Column(name = "role")
    private Role role;

}
public interface AuthRepository extends JpaRepository<User, Integer> {

    Optional<User> findByUsername(String username);

}

Custom UserDetailsService

Sebenarnya ada beberapa cara spring-security menangani JDBC autentikasi, namun menurut saya cara yang paling mudah dan fleksibel adalah dengan membuat implementasi class UserDetailsService. Dimana pada class ini kita mendeklarasikan bagaimana spring-sacurity dapat mengakses table user untuk mendapatkan informasi credential untuk proses autentikasi. Berikut contohnya:

@Service
public class AuthService implements UserDetailsService {

    @Autowired
    private AuthRepository authRepository;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = authRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));

        return org.springframework.security.core.userdetails.User
                .withUsername(user.getUsername())
                .password(user.getPassword())
                .authorities(new SimpleGrantedAuthority(user.getRole().toString()))
                .build();
    }

}

Ketika membuat implementasi class UserDetailsService terdapat method loadUserByUsername() dimana pada method inilah kita mendeklarasikan bagaimana spring-security mengakses database untuk mendapatkan informasi credential user untuk keperluan autentikasi.

Semua kode program lengkap dari contoh diatas dapat diakses disini.

ref: