본문 바로가기
관리자

Programming-[Backend]/Spring Security

[스프링 시큐리티] [작성중] 6. 권한 설정, 표현식

728x90
반응형

 

1. 권한 설정

 

권한 설정 방식

권한 설정은 2가지 방식을 통해 가능하다.

 

1. 선언적 방식

  • URL : http.antMatchers("/users/**").hasRole("USER")
  • method : @PreAuthorize("hasRole('USER')")

 

2. 동적 방식

DB에 연동하여 URL이나 Method로 권한을 설정한다.

 

동적 방식은 나중에 다룰 실전 프로젝트에서 다루고, 일단은 선언적 방식에 대해서만 공부한다.

 

 

선언적 방식

대략 아래 코드와 같은 방식으로 설정해준다고 보면된다. .antMatchers() 메서드를 이용하는데 어떤 url에 대한 것인지, 그리고 chaining을 통해서 어떤 권한을 가진 사용자가 해당 url에 접근해줄 수 있는지를 설정해준다.

 

주의할 점은 하위 계층의 구체적인 url 정보가 먼저 와야한다는 것이다. antMatcher는 위에서부터 한 줄씩 실행되는데, 더 상위의, 큰 범위의 url이 먼저 와버리면 하위 계층은 무시되버리기 때문이다. 예를 들어 아래에서  맨 아래에서 2, 3번째 줄이 바뀌었다고 가정해보자. 그러면 '/erp/admin/expenses' url에 대해 권한이 주어지기전에, '/erp/admin/**' 라는 /admin 하위의 전체 경로에 대해 권한이 주어진다면 'SYS'라는 권한을 가진 사용자도 /expenses에 대한 접근이 가능해져버린다.

 

http
                .antMatcher("/erp/**")
                .authorizeRequests()
                .antMatchers("/erp/login", "/erp/users/**").permitAll()
                .antMatchers("/erp/mypage").hasRole("USER")
                .antMatchers("/erp/admin/expenses").access("hasRole('ADMIN')")
                .antMatchers("/erp/admin/**").access("hasRole('ADMIN') or hasRole('SYS')")
                .anyRequest().authenticated();

 

 

스프링 시큐리티 표현식

 

스프링 시큐리티에서의 표현식은 아래와 같다(참조2). 하나 유의할 점은 isAnonymous()의 경우 앞선 글에서 배운 바대로 anonynous 인증 객체를 가진 상태이기 때문에, 일반 유저로 로그인하여 Role_USER 권한을 가진 경우 접근이 불가하다. 모든 사용자가 접근이 가능하도록 만들고 싶다면, permitAll을 해야한다.

 

 

표현식설명

hasRole(String role) 해당 롤을 가지고 있는 경우 true
hasAnyRole(String… roles) 해당 롤 중에 하나를 가지고 있는 경우 true
isAnonymous() 익명 사용자인 경우 true
isRememberMe() Remember Me 인증을 통해 로그인한 경우 true
isAuthenticated() 이미 인증된 사용자인 경우 true
isFullyAuthenticated() Remember Me가 아닌 일반적인 인증 방법으로 로그인한 경우 true
permitAll 항상 true
denyAll 항상 false
principal 인증된 사용자의 사용자 정보(UserDetails 구현한 클래스의 객체) 반환
authentication 인증된 사용자의 인증 정보**(Authentication** 구현한 클래스의 객체) 반환

 

 


 

2. 권한 실습

 

메모리 방식으로 사용자를 만들고, 권한에 따라서 스프링 시큐리티가 처리하는 방식을 학습해본다. 위 이론에서 배운 바와 같이 선언적으로 권한을 설정하는 방법을 적용할 것이다. 다만 이 방법은 실무에서는 사용하지 않는다. 사용자의 정보가 추가되고, 권한 설정을 해줌에 따라서 동적으로 계속 자원들에 대한 접근이 변경되어야 하기 때문에 보통 DB를 이용하여 동적인 방식을 사용한다. 아래 실습 내용은 단지 권한을 적용하고 어떤 방식으로 작동하는지만 이해하기 위한 것이다.

 

사용자 생성

사용자를 생성해주는 클래스는 AuthenticationManagerBuilder 이다. 아래 코드와 같이 사용자 및 권한 설정을 해주자.

 

@Override
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");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()  //요청에 대한 보안 설정을 시작함
            .antMatchers("/user").hasRole("USER")
            .antMatchers("/admin/expenses").hasRole("ADMIN")
            .antMatchers("/admin/**").access("hasRole('ADMIN') or hasRole('SYS')")
            .anyRequest().authenticated();  //어떤 요청이든 authentication(인가) 과정을 거치도록 한다.
            }

 

AuthenticationManagerBuilder의 configuer를 SecurityConfig 파일에서 Override 해주면 된다. 여기서 메모리 방식을 적용하기 위해서 inMemoryAuthentication() 메서드를 사용했다. 그리고 User, password, role을 정의한다. password 부분 앞에 {noop} 접두어는 비밀번호를 시큐리티가 해싱할때 쓸 알고리즘을 정해주는 부분이다. 이 알고리즘의 종류를 정해주어야 나중에 로그인 시 비밀번호 매칭을 할 때 해당 알고리즘을 사용하여 올바른 인증 과정을 거치게 된다. 만약 알고리즘을 설정해주지 않으면 에러가 발생하니 유의해야 한다. noop은 어떠한 알고리즘도 적용하지 않고 입력한 비밀번호(1111)을 그대로 사용하겠다는 것이다.

 

roles는 admin의 경우 3가지 권한을 모두 부여했다. 상식적으로는 admin은 ADMIN 권한만 갖고 있으면 될 것 같은데, 여기서는 권한 계층 설정이 되지 않았기 때문에 직접 모든 권한을 다 부여해야한다. 권한 계층 설정에 대해서는 뒤에서 배우게 된다.

 

아래와 같이 컨트롤러를 작성하고 실습한다. 권한이 지정되지 않은 아이디로 자원에 접근하면 403 forbidden 에러가 발생하는 것을 확인할 수 있다.

 

@GetMapping("/user")
public String user() {
    return "user";
}

@GetMapping("/admin/expenses")
public String adminExpenses() {
    return "adminExpenses";
}

@GetMapping("/admin/**")
public String admin() {
    return "admin";
}

 

 

 

 

 

 


 

참조

 

1) 인프런 - 스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security - 정수원님 강의

https://www.inflearn.com/course/%EC%BD%94%EC%96%B4-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0

 

 

2) ChanGrea.io 블로그

https://changrea.io/spring/spring-security-authorization/

 

728x90
반응형