Spring Security - udemy

[섹션3] 유저 정의와 관리 - JdbcIserDetailsManager를 사용한 유저 설정

샐님 2024. 8. 16. 10:32
728x90
반응형

 

 

db에 spring security 가 원하는 명명 규칙을 따라야 한다.  (JdbcUserDetailsManager 사용시 필요한 명명규칙)

관련 스크립트 : users.ddl 에 위치, 해당 스크립트를 복사해서 테이블 생성

create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null);
create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);

 

이코드를 그대로 복사해 ms sql 실행하면 오류 발생 -> mssql 문법에 맞게 수정 후 실행

 

 

create table users(username nvarchar(50) not null primary key,password nvarchar(500) not null,enabled bit not null);
create table authorities (username nvarchar(50) not null,authority nvarchar(50) not null,constraint fk_authorities_users foreign key(username) references users(username));
create unique index ix_auth_username on authorities (username,authority);

 

 

config 폴더의 ProjectSecuityConfig.java

package woncompany.springsecestion3.config;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

import javax.sql.DataSource;
@Configuration
public class ProjectSecurityConfig {

    // section3 jdbc 인증 방식을 사용해 데이터베이스에 기록과 유저 정보를 저장함
    // 1. jdbcUserDetailsManager 타입의 Bean 을 생성
    // application.properties에서 정의할 때마다 Spring Boot는 DataSource 객체를 자동적으로 웹 애플리케이션 내부에 생성
    // 즉, 이 DataSource 객체가  jdbcUserDetailsManager 에게 넘어갈 때마다 발생
    // spring security 가 jdbc 인증 방식을 사용한다는 것을 이해하며 데이터 베이스 정보를 가지고 있음
    @Bean
    public UserDetailsService userDetailsService(DataSource dataSource){
        return new JdbcUserDetailsManager(dataSource);
    }
    // 비밀번호를 어떻게 저장하였는지 알려주어야 함
    // 일반 텍스트 or 암호화 와 해싱을 이용했는지.. 그러므로 항상 필요함
    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.csrf((csrf) -> csrf.disable())
                .authorizeHttpRequests((requests)->requests
                        .requestMatchers("/myAccount","/myBalance","/myLoans","/myCards").authenticated()
                        .requestMatchers("/notices","/contact","/register").permitAll())
                .formLogin(Customizer.withDefaults())
                .httpBasic(Customizer.withDefaults());
        return http.build();
    }



}

 

하지만 실제 기업 애플리케이션에서는 고객의 요구사항에 따라 명명 규칙이 다를수 도 있다. 

 

맞춤형 UserDetailsService 구현

 

 

customer 테이블 생성

CREATE TABLE [dbo].[customer](
	[id] [decimal](18, 0) IDENTITY(1,1) NOT NULL,
	[email] [nvarchar](200) NULL,
	[pwd] [nvarchar](200) NULL,
	[role] [nvarchar](100) NULL
) ON [PRIMARY]

 

model 패키지 생성 -> Customer.java 

package woncompany.springsecestion3.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;

@Entity
@Data
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String email;
    private String pwd;
    private String role;
}

 

config 패키지 -> BankUserDetails.java 파일 생성

package woncompany.springsecestion3.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;
import woncompany.springsecestion3.model.Customer;
import woncompany.springsecestion3.repository.CustomerRepository;

import java.util.ArrayList;
import java.util.List;


@Service
public class BankUserDetails implements UserDetailsService {


    @Autowired
    CustomerRepository customerRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String userName, password = null;
        List<GrantedAuthority> authorities =null;
        List<Customer> customer = customerRepository.findByEmail(username);
        if(customer.size()==0){
            throw new UsernameNotFoundException("User details not found for the user :" +username);

        }else{
            userName = customer.get(0).getEmail();
            password = customer.get(0).getPwd();
            authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority(customer.get(0).getRole()));



        }

        return new User(username,password,authorities);
    }
}

 

728x90
반응형