웹 프로그래밍/[ Spring Security ]

[ Spring Security ] 04. 인가 API와 표현식

kim.svadoz 2021. 12. 9. 16:46
반응형
인프런에서 진행하는 정수원 강사님의 "스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security" 강의를 보고 학습을 위해 개인적으로 추가/정리한 글임을 알립니다.

인가 API


[ 권한설정과 표현식 ]

  • 선언적 방식
    • URL
      • http.antMatchers("/users/**").hasRole("USER")
    • Method
      • @PreAuthorize("hasRole('USER')")
      • public void user() { System.out.println("user"); }
  • 동적 방식 (DB 연동 프로그래밍)
    • URL
    • Method

 

> 권한 설정

protected void configure(HttpSecurity http) throws Exception {
    http
        .antMatcher("/shop/**")                        // 해당 설정한 경로로 요청할 때만 보안 기능이 작동하게 된다. 이걸 생략하면 모든 경로에 적용
        .authorizeRequest()
            .antMatchers("/shop/login", "/shop/users/**").permitAll() // 해당 경로로 접근하는 모든 요청에 대해 허용 하겠다.(인가 허용)
            .antMatchers("/shop/mypage").hasRole("USER") // mypage로 접근하는 사용자는 USER라는 역할이어야 한다.
            .antMatchers("/shop/admin/pay").access("hasRole('ADMIN')");
            .antMatchers("/shop/admin/**").access("hasRole('ADMIN') or hasRole('SYS ')");
            .anyRequest().authenticated()        // 위의 요청을 제외하고서는 모든 요청에 대해서 인증을 받은 사용자 만이 어떤 자원에 접근가능하다.
    ;
}
// 여기서 모든 절차를 거쳐야 인가를 통과하고 해당 자원에 접근할 수 있다.

이 때 주의사항은 설정시 구체적인 경로가 먼저 오고 그것보다 큰 범위의 경로가 뒤에 와야 한다.

스프링 시큐리티는 위에서부터 아래로 순서대로 인가처리를 하게 되기 때문이다.

 

> 표현식

메소드 동작
authenticated() 인증된 사용자의 접근을 허용
fullyAuthenticated() 인증된 사용자의 접근을 허용, rememberMe 인증은 제외
permitAll() 무조건 접근을 허용
denyAll() 무조건 접근을 허용하지 않음
anonymous() 익명사용자의 접근을 허용
rememberMe() 기억하기를 통해 인증된 사용자의 접근을 허용
access(String) 주어진 SpEL 표현식의 평과 결과가 true이면 접그을 허용
hasRole(String) 사용자가 주어진 역할이 있다면 접근을 허용
hasAuthority(String...) 사용자가 주어진 권한이 있다면 접근을 허용
hasAnyRole(String...) 사용자가 주어진 권한이 있다면 접근을 허용
hasAnyAuthority(String...) 사용자가 주어진 권한 중 어떤 것이라도 있다면 접근을 허용
hasIpAddress(String) 주어진 IP로부터 요청이 왔다면 접근을 허용

 

특이한것은 인증된 사용자는 anonymous()에서 접근이 불가능하다. 익명사용자 메소드는 오로지 익명사용자만 접근하기 위한 메소드이다.

 

Spring Security 5부터 password를 암호화 할 때 특정한 패스워드 유형 알고리즘의 방식을 prefix형태로 표시해야 한다.

그래야 나중에 패스워드를 검사하고 매치할 때 어떤 유형으로 패스워드 알고리즘을 통해 저장하고 암호화 했는지 알 수 있다.
(prefix가 없다면 id가 null로 뜬다.)

{noop} : 1111 그대로, 평문으로 사용한다는 prefix이다.

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("user").password("{noop}1111").roles("USER");
    auth.inMemoryAuthentication().withUser("sys").password("{noop}1111").roles("SYS","USER");
    auth.inMemoryAuthentication().withUser("admin").password("{noop}1111").roles("ADMIN","SYS","USER");
}

 

현재는 메모리형식으로 했지만 실제로는 DB를 통해서 동적으로 관리자 시스템에서 사용자를 생성하고 관리해야 할 것이다.

해당 자원에 대한 권한 설정도 운영서비스에서 실시간적으로 필요에 의해서 설정이 되어야 하고, 이는 다음에 더 자세하게 다뤄볼 예정이다.

반응형