Spring Security : JDBC를 이용한 인증

yewo2nn16·2022년 7월 1일
0

Spring

목록 보기
2/7

spring security JDBC를 이용해 간단한 로그인을 구현해봅니다.

시작하기 전에

저는 아래의 것을 사용합니다.
Gradle , lombok , MySql

데이터베이스 설계와 테이블 DTO 작성이 필요합니다.

1. 데이터베이스 설계

데이터베이스 정보를 이용해 로그인 하기 위해서는 우선 테이블을 설계 해야합니다.

간단히 사용자 user 테이블과 권한 role 테이블이 필요하며, 이 두 테이블은 다대다 관계 를 가집니다.
따라서 연결 테이블 user_role 을 사용합니다.

user 테이블의 username 이 로그인 아이디가 됩니다.

로그인을 위해 임의의 데이터를 넣어두겠습니다.

username은 test , password는 1234 를 암호화한 값을 넣어줍니다.

INSERT INTO user(id, username, password, enabled)
VALUES(1, 'test', '$2a$10$PSVJfM/zxo4.CHq5QZHWZulFo/dT0SSiUxUNOWu1.lypNG16h0.8C', 1);
INSERT INTO role(id, authority) VALUES(1, 'ROLE_USER');
INSERT INTO user_role(user_id, role_id) VALUES(1, 1);

사용자가 test / 1234 로 로그인할 수 있으며, ROLE_USER 권한을 갖고 있습니다.

2. 테이블 DTO 작성

user 테이블과 role 테이블에 대한 DTO를 작성합니다.
이때 @ManyToMany , @JoinTable 어노테이션을 이용해 다대다 관계와 연결 테이블을 지정해줍니다.

@Data
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String password;

    private Boolean enabled;

    @ManyToMany
    @JoinTable(
            name = "user_role",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private List<Role> roles = new ArrayList<>();
}
@Data
@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String authority;

    @ManyToMany(mappedBy = "roles")
    private List<User> users;
}

스프링 시큐리티 적용

본격적으로 spring security를 구현해보겠습니다.

3. 의존성 추가

먼저 의존성을 추가해 줍니다.

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'

4. Config 클래스 작성

스프링 시큐리티 Config 클래스는 WebSecurityConfigurerAdapter 를 상속받으며
@EnableWebSecurity 어노테이션을 추가합니다.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter  {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/", "/register").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
    }
}

스프링 시큐리티 설정은 HttpSecurity 로 합니다.

.authorizeRequests() 리소스의 권한을 설정합니다.
.antMatchers("/", "/register").permitAll() : / 또는 /register 에 대한 접근은 모두 허용합니다.
.anyRequest().authenticated() : 그 외 나머지 리소스는 인증된 사용자만 접근할 수 있습니다.

.formLogin()로그인 처리를 설정합니다.
로그인 form 페이지를 이용하여 로그인하는 방식입니다.
.loginPage("/login") : 로그인 페이지를 지정합니다. 사용자가 만든 로그인 페이지를 사용하려 할 때 설정하며, 설정하지 않으면 스프링이 제공하는 기본 로그인 페이지가 호출됩니다.
로그인 성공 시 이동할 페이지, 실패 시 이동할 페이지 등도 지정할 수 있습니다.

.logout()로그아웃 처리를 설정합니다.

5. 로그인 인증 처리

AuthenticationManagerBuilder 를 이용해 로그인 인증을 처리합니다.

@Autowired
private DataSource dataSource;
    
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
    throws Exception {
        auth.jdbcAuthentication()
            .dataSource(dataSource)
            .passwordEncoder(passwordEncoder())
            .usersByUsernameQuery("select username, password, enabled "
                + "from user "
                + "where username = ?")
            .authoritiesByUsernameQuery("select u.username, r.authority "
                + "from user_role ur inner join user u on ur.user_id = u.id "
                + "inner join role r on ur.role_id = r.id "
                + "where u.username = ?");
}

@Bean
public static PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

auth.jdbcAuthentication() : DB 기반의 인증을 처리하도록 합니다.
.dataSource(dataSource) : dataSource를 지정해줍니다.
.passwordEncoder(passwordEncoder()) : 패스워드 암호화를 적용합니다.
.usersByUsernameQuery() : 사용자 목록을 가져오는 쿼리를 작성합니다. 출력 결과는 사용자이름 , 비밀번호 , enabled 로 총 3개여야 합니다.
.authoritiesByUsernameQuery() : 권한을 불러오는 쿼리를 작성합니다. 출력 결과는 사용자이름, 권한명 으로 총 2개여야 합니다.

6. 결과

로그인 하지 않은 상태에서 /board/list 로 접속하면 로그인 페이지로 이동됩니다.

로그인 한 뒤 접속할 수 있습니다.

profile
개미는 뚠뚠 🐜🐜

0개의 댓글