[spring boot] spring security란?

이경민·2022년 10월 2일
0

spring

목록 보기
18/20

Spring Security

Spring에서는 Spring Security라는 별도 프레임워크에서 인증 (Authentication)과 안가 (Authorization) 기능을 제공한다.

  • 인증 (Authentication): 사용자 본인 확인
  • 안가 (Authorization): 인증된 사용자가 요청한 자원에 접근 가능한지 결정
    인증 성공 후 인가가 이루어진다


SecurityConfig

인증/인가 API들의 설정을 제공

import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration                // IoC 빈(bean)을 등록
@EnableWebSecurity            // 필터 체인 관리 시작 어노테이션
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)    // 특정 주소 접근시 권한 및 인증을 위한 어노테이션 활성화
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder encodePwd() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/user/**").authenticated()
                //.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')")
                //.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN') and hasRole('ROLE_USER')")
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .anyRequest().permitAll()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/loginProc")
                .defaultSuccessUrl("/");
    }

}

WebSecurityConfigurerAdapter 클래스

  • 스프링 시큐리티의 웹 보안 기능의 초기화 및 설정들을 담당하는 내용이 담김.
  • 내부 적으로 getHttp()메서드가 실행될 때 HTTPSecurity 클래스를 생성하게 됩니다.

SecurityConfig class 특징

  • EnableWebSecurity 어노테이션: Securiry를 활성화
  • configure(HttpSecurity http)메서드를 override

HttpSecurity 설정

  • 리소스(URL) 접근 권한 설정 -> antMatchers
  • 인증 전체 흐름에 필요한 Login, Logout 페이지 인증완료 후 페이지 인증 실패 시 이동페이지 등등 설정
  • 인증 로직을 커스텀하기 위한 커스텀 필터 설정
  • 기타 csrf, 강제 https 호출 등등 거의 모든 스프링시큐리티의 설정

BCryptPasswordEncoder

  • bcrypt'라는 해시 함수를 이용해서 패스워드를 암호화하는 목적으로 설계된 클래스
  • 스프링 부트 2.0부터는 인증을 위해서 반드시 지정


User

import java.sql.Timestamp;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.CreationTimestamp;

import lombok.Data;

@Data
@Entity
public class User {
    @Id // primary key
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    private String email;
    private String role; //ROLE_USER, ROLE_ADMIN

    @CreationTimestamp
    private Timestamp createDate;
}


PrincipalDetails

로그인 시, JWT 토큰을 생성해서 반환

import com.example.instaspringsecurity.model.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;

@Data
public class PrincipalDetails implements UserDetails {
    private User user;

    public PrincipalDetails(User user) {
        super();
        this.user = user;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collet = new ArrayList<GrantedAuthority>();
        collet.add(()->{ return user.getRole();});
        return collet;
    }

}

UserDetails

  • 인터페이스이며, User는 이 인터페이스를 구현한 객체
  • 인증에 성공하여 생성된 UserDetails 객체는 Authentication 객체를 구현한 UsernamePasswordAuthenticationToken을 생성하기 위해 사용.

Collection

접근 주체는 Authentication 객체 생성.

  • 이 객체는 SecurityContext(내부 메모리)에 보관되고 사용되어진다.


PrincipalDetailsService

import com.example.instaspringsecurity.model.User;
import com.example.instaspringsecurity.repository.UserRepository;
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 PrincipalDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if(user == null) {
            return null;
        }
        return new PrincipalDetails(user);
    }
    
}

UserDetailsService 인터페이스

  • DB로부터 사용자를 가져와 로그인 처리 로직을 구현하는 역할.
  • UserDetails 객체를 반환하는 단 하나의 메소드를 가지고 있다.
  • 일반적으로 구현 클래스 내부에 UserRepository를 주입받아 DB와 연결하여 처리.

loadUserByUsername 함수

return 값으로 UserDetails를 구현한 객체를 return



UserRepository

import com.example.instaspringsecurity.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Integer> {
    User findByUsername(String username);
}

DB 역할을 하게 될 Repository 클래스. Map을 통해 사용자들을 가진다

0개의 댓글