[Spring] Security spring

유형찬·2022년 11월 18일
0

스프링 시큐리티 따라잡기 SSR 편

사실 스프링 시작 하는 사람들에게 있어서 가장 어려운 부분이 아닐 까 생각 된다.

보안이라는게 사실 타협 할 수 없는 부분이고 그래서 스프링 시큐리티를 잘 이해 하고 사용 해야 한다.

그래서 이번에는 스프링 시큐리티를 따라잡아 보려고 한다.

이게 사실 스프링을 시작한지 얼마 안된 사람들에게 가장 큰 벽이 아닐까...

Gradle 설정

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.1.0'

SSR 설정을 위해서 thymeleaf 설정과 security 설정을 해준다.

필요한 Class 목록

User extends UserDetails

UserRepository extends JpaRepository

UserService extends UserDetailsService

SecurityConfig extends WebSecurityConfigurerAdapter

SecurityController extends Controller

public class User implements UserDetails {
    private String username;
    private String password;
    private String email;
    private String name;
    private String phone;
    private String address;
    private String role;
    private boolean enabled;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private Collection<? extends GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
        // return Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"));
        // return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
        // return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"), new SimpleGrantedAuthority("ROLE_ADMIN"));
        // return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"), new SimpleGrantedAuthority("ROLE_ADMIN"), new SimpleGrantedAuthority("ROLE_MANAGER"));
        // return createAuthorities(List.of("ROLE_USER", "ROLE_ADMIN", "ROLE_MANAGER"));
    }
  /*  public List<GrantedAuthority> createAuthorities(List<String> roles) {
        List<GrantedAuthority> authorities = roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
        return authorities;
    }*/

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

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

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

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

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

권한이 여러개인 경우... authorities를 List로 만들어서 넣어주면 된다.

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}
@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

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

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/signup").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }
}

위처럼 configuration 을 해줘도 되고 아래와 같이 설정도 가능하다.
위는 스프링 security에 관한 filter 만을 사용하고 아래는 스프링 security에 관한 filter 와 기존의 filter 를 사용한다.

@Configuration
public class SecurityConfiguration{

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

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/signup").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll()
                .and()
                .logout()
                .permitAll();
        return http.build();
    }
}

사실 이렇게 설정을 해주면 끝이다.

음 security user 정보를 사용하기 위한 방법이 정말 많은데 이번에는 userDetails 를 사용 했다.

위 5가지 클래스만 잘 만들어주면 된다.

사실 이렇게 하면 권한이 하나인 경우에는 괜찮지만 권한이 여러개인 경우에는 좀 더 코드를 이쁘게 짜야할 것 같다.

profile
rocoli에요

0개의 댓글