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
반응형