์ฅ๊ณ ์์๋ ํ์ฌ request๋ฅผ ๋ณด๋ธ ํด๋ผ์ด์ธํธ ์ ๋ณด๋ฅผ ํ ๋๋ก ํน์ ๋ฉ์๋ ์ ๊ทผ ๊ถํ์ ์์ธํ๊ฒ ์ค์ ํ ์ ์๋ ๊ธฐ๋ฅ์ ์ฝ๊ฒ ์ ๊ณตํ๊ณ ์์๋ค.
๋จ์ํ ๋ก๊ทธ์ธ ์ ๋ฌด๋ ADMIN, USER๊ฐ ์๋๋ผ 'ํน์ ๊ทธ๋ฃน์ ์์๋์ด ์๋๊ฐ?'๋ฅผ ๋ฐ์ง๋ ค๋ฉด ์ปค์คํ
๊ธฐ๋ฅ์ด ํ์ํ๋ค.
์คํ๋ง์์ ์ด ๊ธฐ๋ฅ์ ๋๋ ๊ฒ์ด PreAuthorize์ธ๋ฐ, ๋ฌผ๋ก ๋ด๊ฐ ์ํ๋ ๊ธฐ๋ฅ์ ์ํด์๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ ์ปค์คํ
ํด์ผ๋ง ํ๋ค.
์ด ๊ณผ์ ์์ ๋๋ฌด ์ค๋ ์๊ฐ์ด ์์๋์ด ๊ฒฐ๊ณผ์ ์ผ๋ก ์คํจํ๋ค.
public class CustomSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
private ApplicationContext applicationContext;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, MethodInvocation invocation
) {
CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
root.setThis(invocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(this.trustResolver);
// root.setRoleHierarchy(getRoleHierarchy());
root.setReturnObject(invocation.getThis());
return root;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
super.setApplicationContext(applicationContext);
this.applicationContext = applicationContext;
}
}
๋ด ์ถ์ธก์ด์ง๋ง MethodSecurityExpressionRoot
๋ฅผ ์ง์ ์ ์ผ๋ก ์์ ํ ์ ์์ด์ DefaultMethodSecurityExpressionHandler
๋ฅผ ํตํด ๊ฐ์ ์ ์ผ๋ก ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ผ ํ๋๋ฐ, ๋ฒ์ ์ด ๋ฐ๋๋ฉด์ ๋ญ๊ฐ ๋ฐฉ๋ฒ์ด ๋ฐ๋ ๊ฒ ์๋๊น ์ถ๋ค.
์จ๊ฐ ๋ธ๋ก๊ทธ๋ฅผ ๋ค ๋ค์ง๊ณ ๋ช ์๊ฐ์ ๊ณ ๋ฏผํ๋ค๊ฐ ๋์ ํ ์๊ฐ์ด ๋ถ์กฑํ๋ค๋ ํ๋จ์ด ๋์ด ๊ผผ์๋ฅผ ํตํด ๋ฌธ์ ๋ฅผ ์ผ๋จ ํํผํ๋ค.
@Service("securityService")
@RequiredArgsConstructor
@Log4j2
public class SecurityService {
private final UserSearchService userSearchService;
private final Logger logger = Logger.getLogger(SecurityService.class.getName());
Authentication authentication;
ServletRequestAttributes attributes;
public boolean isLeader(Long group_id) {
authentication = SecurityContextHolder.getContext().getAuthentication();
User user = userSearchService.findUserById(((User) authentication.getPrincipal()).getUser_id()).orElseThrow(()
-> new RuntimeException("ํด๋น ์ ์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค."));
log.info("isLeader = {}", user);
boolean is_leader = user.getIs_leader().stream().anyMatch(group -> group.getGroup_id().equals(group_id));
if (!is_leader)
exception_handling();
return is_leader;
}
public boolean isMember(Long group_id) {
authentication = SecurityContextHolder.getContext().getAuthentication();
User user = userSearchService.findUserById(((User) authentication.getPrincipal()).getUser_id()).orElseThrow(()
-> new RuntimeException("ํด๋น ์ ์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค."));
log.info("isMember = {}", user);
boolean is_member = user.getMembers().stream().anyMatch(member -> member.getGroup().getGroup_id().equals(group_id));
if (!is_member)
exception_handling();
return is_member;
}
public boolean isPayer(Long receipt_id) {
authentication = SecurityContextHolder.getContext().getAuthentication();
User user = userSearchService.findUserById(((User) authentication.getPrincipal()).getUser_id()).orElseThrow(()
-> new RuntimeException("ํด๋น ์ ์ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค."));
log.info("isPayer = {}", user);
boolean is_payer = user.getPay_receipts().stream().anyMatch(receipt -> receipt.getReceipt_id().equals(receipt_id));
if (!is_payer)
exception_handling();
return is_payer;
}
private void exception_handling() {
attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
// String currentUrl = attributes.getRequest().getRequestURI();
// String currentUrl = attributes.getRequest().getRequestURL().toString();
// XXX: ์ ๋ขฐํ ์ ์๋ url. ์ข์ง ์๋ค.
String currentUrl = attributes.getRequest().getHeader("referer");
attributes.getRequest().getSession().setAttribute("accessDeniedUrl", currentUrl);
}
log.info("attributes = {}", attributes);
throw new AccessDeniedException("You do not have permission to access this resource.");
}
}
@DeleteMapping("/{receipt_id}/delete")
@PreAuthorize("@securityService.isPayer(#receipt_id)")
public ResponseEntity<String> delete(@PathVariable(value = "group_id") Long group_id,
@PathVariable(value = "meeting_id") Long meeting_id,
@PathVariable(value = "receipt_id") Long receipt_id) {
receiptManageService.delete(receipt_id);
return ResponseEntity.ok("receipt delete success");
}