SpringBoot Meteor
[Spring Boot] Spring Security 시큐리티 권한 업데이트 시 동적 적용
DoubleMeteor
2021. 12. 21. 13:31
관리자 페이지에서 회원에 따른 권한을 변경하였을 때 재 로그인을 하지 않더라도
변경된 권한이 적용되어 권한이 걸린 경로로 접근하는 것을 막고 싶을 때
(로그아웃을 시킨뒤에 다시 로그인 플로우를 진행하게되면 사용자의 불편함이 예상, 그리고 권한이 바뀐 이후의
시점에도 로그아웃(세션을 끊음)을 하지않는다면 로그아웃 이전까지의 권한이 유지됨)
최초 로그인 시에 SpringSecurity가 계정 정보를 관리할 수 있도록 Authentication객체를 만들어준다.
이 Autentication객체 안에는 로그인 시점의 계정 정보를 담고 있다.
사용자의 권한이 변경 또는 추가가 되어도 update된 정보에 대해서는 Authentication객체에는 현행화(동기화)가 되지않았기 때문이다. 즉, Security가 게정정보를 관리하고있는 객체가 update되지 않았다는 말이다.
해결방법 → 유저의 권한 변경이 일어나는 시점에 기존 시큐리티가 가지고 관리하고있던 Autentication 객체의
권한만 수정(update)해주면 된다.
기존 객체에 동적으로 새로운 권한을 추가해보자.
- 우선 Autentication객체가 들고있는 기존 계정의 권한 정보를 가지고 온다
// 기존 계정의 정보를 들고온다.
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// 새로운 권한을 넣기위해 리스트를 하나 생성한다 (단일 권한일시에는 리스트로 할 필요 없음)
List updatedAuthorities = new ArrayList<>();
- 권한을 추가하거나(add), 새로운 권한을 부여한다 (cleart → add)
updatedAuthorities.add(new SimpleGrantedAuthority(userRoleType.getRole().getValue()));
- update한 권한정보로 다시 Security가 관리할 수 있는 객체를 생성해준다.
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
- 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);
}
회원 권한을 수정한 후 → 시큐리티 객체 정보를 업데이트(동기화) 시켜 줌
로그아웃 → 로그인을 따로하지 않더라도 시큐리티 객체정보가 업데이트 됨으로 리로드될 시에 다시 권한을 체크 가능 이후
짜놓은 로직 플로우 대로 실행