ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot] Spring Security 시큐리티 권한 업데이트 시 동적 적용
    SpringBoot Meteor 2021. 12. 21. 13:31

    관리자 페이지에서 회원에 따른 권한을 변경하였을 때 재 로그인을 하지 않더라도

    변경된 권한이 적용되어 권한이 걸린 경로로 접근하는 것을 막고 싶을 때

    (로그아웃을 시킨뒤에 다시 로그인 플로우를 진행하게되면 사용자의 불편함이 예상, 그리고 권한이 바뀐 이후의

    시점에도 로그아웃(세션을 끊음)을 하지않는다면 로그아웃 이전까지의 권한이 유지됨)

    최초 로그인 시에 SpringSecurity가 계정 정보를 관리할 수 있도록 Authentication객체를 만들어준다.

    이 Autentication객체 안에는 로그인 시점의 계정 정보를 담고 있다.

    사용자의 권한이 변경 또는 추가가 되어도 update된 정보에 대해서는 Authentication객체에는 현행화(동기화)가 되지않았기 때문이다. 즉, Security가 게정정보를 관리하고있는 객체가 update되지 않았다는 말이다.

    해결방법 → 유저의 권한 변경이 일어나는 시점에 기존 시큐리티가 가지고 관리하고있던 Autentication 객체의

    권한만 수정(update)해주면 된다.

    기존 객체에 동적으로 새로운 권한을 추가해보자.

    1. 우선 Autentication객체가 들고있는 기존 계정의 권한 정보를 가지고 온다
    // 기존 계정의 정보를 들고온다.
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    
    // 새로운 권한을 넣기위해 리스트를 하나 생성한다 (단일 권한일시에는 리스트로 할 필요 없음)
    List updatedAuthorities = new ArrayList<>();
    1. 권한을 추가하거나(add), 새로운 권한을 부여한다 (cleart → add)
    updatedAuthorities.add(new SimpleGrantedAuthority(userRoleType.getRole().getValue()));
    1. update한 권한정보로 다시 Security가 관리할 수 있는 객체를 생성해준다.
    Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
    
    1. Security가 관리하고있는 객체를 3에서 변경된 대상으로 다시 변경해준다(동기화)
    // SecurityContextHolder의 Authentication에 새로운 객체정보로 update시켜줌 
    SecurityContextHolder.getContext().setAuthentication(newAuth);
    
    • 전체코드
    /**
         * 회원 권한 수정
         * @param userRoleType 회원 idx, 권한
         * @return HttpEntity
         */
        @PutMapping
        public HttpEntity<?> memberRoleUpdate(@RequestBody AdminMemberRoleUpdateDTO userRoleType ) {
    
            AdminRoleUpdateDTO adminRoleUpdateDTO = memberAdminService.memberRoleUpdate(userRoleType);
            if (adminRoleUpdateDTO == null) {
                return new ResponseEntity<>(new ResponseDTO<>(ResponseEnum.MEMBER_ROLE_UPDATE_FAIL), HttpStatus.EXPECTATION_FAILED);
            }
    
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            List<GrantedAuthority> updatedAuthorities = new ArrayList<>();
            updatedAuthorities.add(new SimpleGrantedAuthority(userRoleType.getRole().getValue()));
            Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
            SecurityContextHolder.getContext().setAuthentication(newAuth);
    
            return new ResponseEntity<>(new ResponseDTO<>(ResponseEnum.MEMBER_ROLE_UPDATE_SUCCESS, adminRoleUpdateDTO), HttpStatus.OK);
        }
    

    회원 권한을 수정한 후 → 시큐리티 객체 정보를 업데이트(동기화) 시켜 줌

    로그아웃 → 로그인을 따로하지 않더라도 시큐리티 객체정보가 업데이트 됨으로 리로드될 시에 다시 권한을 체크 가능 이후

    짜놓은 로직 플로우 대로 실행

Designed by Tistory.