본문 바로가기
프로젝트/SpringSecurity

[Spring Security] 3. 권한부여&오류수정과정

by dantriss 2023. 7. 4.

유튜브에서 스프링시큐리티를 심화교육하면서 조금더 레벨업 하고자 한다.

IDE : IntelliJ

언어 : Java 8

스프링부트 버전 : 2.7.13

DB : MySQL

빌드관리 도구 : Maven

OS : iOS

참고유튜브 : 메타코딩

 


  • SecurityConfig에서 특수한 주소에는 전부 해당 권한이 있는 사용자만 접근가능하게 하기

 

저번글에서 SecurityConfig에 특정권한을 가진 사용자별로 접속할 수 있는 주소에 대해 차이점을 두었었다.

@Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception{

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

        return http.build();

    }

 

다른 사용자를 회원가입해서 권한을 변경해주자

 

모든 유저를 해당방법으로 가입했을 때 권한이 유저로 되어있을텐데

update문으로 권한을 바꿔도 되고

UPDATE user set role = 'ROLE_MANAGER' WHERE username = 'manager';
UPDATE user set role = 'ROLE_ADMIN' WHERE username = 'admin';
commit;

 

IndexController에서 회원가입할 때 조건문을 넣어서 변경해주어도 된다.

 

db에서 확인해보면 각각 다른 권한으로 변경된 것을 확인할 수 있다.

 

간단한 테스트를 위해서 @ResonseBody어노테이션을 추가하고 주소는 /admin /manager로 설정한다.

그러면 SecurityConfig에서 설정한대로 해당 주소에는 

/admin -> admin권한을 가진 사용자만 접근가능

/manager -> admin과  manager권한을 가진 사용자만 접근이 가능할 것이다.

각각 주소에 권한을 준 모습

 

잘 동작하는지 확인해보자

우선 user 권한을 가진 계정으로 로그인해서 /admin과 /manager를 접근해보면 접근을 할 수 가 없다.

 

그에 반해 모든 주소에 접근이 가능한 admin으로 로그인한 뒤 다시 시도해보면 이상없이 접근할 수 있는것을 확인할 수 있다.

 


  • @EnableGlobalMethodSecurity 어노테이션 사용해서 권한이 있는 사용자만 접근가능하게 하기

 

SecurityConfig에서 전체적으로 주소에 권한을 부여할 수도 있지만 모든 주소에 걸지 않고 특별한 주소에서만 막는 방법도 있다.

SecurityConfig에서 해당 어노테이션을 추가한 후 securedEnabled 를 True로 변경하자

@EnableGlobalMethodSecurity(securedEnabled = true)

 

그리고 IndexController로 이동한 후 테스트할 간단한 메서드를 작성한다.

이렇게 작성하면 해당 주소엔 admin 권한을 가진 사용자만 접근이 가능하다.

@Secured("ROLE_ADMIN")
@GetMapping("/info")
public @ResponseBody String info (){

    return "어드민만 볼 수 있습니다";
}

admin으로 접근을 했을 경우
일반 유저로 접근을 한 경우

 

하지만 난 admin과 manager 둘다 접근 가능하게 하고 싶은데 어떻게 하지..?

그렇다면 SecurityConfig에 @EnableGlobalMethodSecurity 어노테이션에서 prePostEnabled를 true로 작성해준다.

 

다시한번 IndexController로 이동해 간단한 테스트를 진행 해보도록하자.

 

manager 또는 admin 으로 접근한 경우

 

일반 유저로 접근을 한 경우

 


  • 작은 실수로 오류가 생겨서 이것저것 찾아보면서 오류의 이유를 찾아가는 과정

admin 과 manager로 아무리 로그인을 하고 /admin 과 /manager로 접근을 시도해도 계속 403 에러가 발생하였다.

SecurityConfig에서 잘 못 작성한것이 있는지 여러번 확인해보고 db에도 ROLE_을 지워보기도하고

다양한 방법으로 권한을 부여도 해보았었다.

다양한 시도를 해보았다.

 

지금은 지원하지 않는 WebSecurityConfigurerAdapter을 상속받아서 시도도 해보았고

오타가 있지는 않은지도 확인했었는데도 원하는대로 동작하지 않아서

로그인을 시도했을때 유저의 정보가 제대로 시큐리티 세션에 저장이 되는지 의심이 갔었다.

일단 로그인 후 /user로 접근을 했을때 모든 사용자가 접근이 가능한 주소인 /user에는 접근이 가능했고

로그인을 하지 않은 상태로 접근을 했을땐 로그인페이지로 이동이 되었다.

즉 스프링시큐리티가 로그인처리를 해주고 세션에 유저의 정보가 저장이 되었다는 것을 확인할 수 있었다.

로그인 후 접근이 가능한 주소 /user

 

그러면 세션에 저장된 유저의 정보를 한번 출력해보도록하자

/user로 접근했을 때 Authentication 을 파라메터로 받아서 로그인한 회원의 아이디와 권한을 출력해보니

 

권한에 비어있는 값을 출력해주었다.

즉 db상에는 admin과 manager, user로 총 3가지로 구분이 되어있지만 해당 값을 세션에 저장하지 못한다는 것을 확인할 수 있다.

 

PrincipalDetails로 이동해서 생성자들을 확인해보았을 때 권한을 리턴해줄 때 null값을 리턴하고 있는것을 확인했다.

기껏 유저의 권한을 추가해주었는데 리턴을 해주지 않았다

 

그래서 유저의 권한 정보를 리턴해주고 다시한번 /user로 접근해보았다.

 

아까와는 다르게 주소를 리턴해주고 있다. 

 

다시 admin으로 로그인 후 /admin으로 접근을 시도 했더니 원하는 결과값이 나오게되었다.

정말 사소한것으로 많은 시간을 소비했지만 이또한 성장해나가는 발판으로 삼는 경험을 했다고 생각한다.

댓글