메소드 시큐리티
- 서비스 계층을 직접 호출할 때 사용하는 보안 기능이다.
 
- AOP 를 이용해서 적용시킨 것이다.
 
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class MethodSecurity extends GlobalMethodSecurityConfiguration {
    @Override
    protected AccessDecisionManager accessDecisionManager() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager();
        accessDecisionManager.getDecisionVoters().add(new RoleHierarchyVoter(roleHierarchy));
        return accessDecisionManager;
    }
}
- @Secured와 @RollAllowed
- 메소드 호출 이전에 권한을 확인한다.
 
- 스프링 EL을 사용하지 못한다.
 
 
- @PreAuthorize와 @PostAuthorize
- 메소드 호출 이전 이후에 권한을 확인할 수 있다.
 
- 스프링 EL을 사용하여 메소드 매개변수와 리턴값을 검증할 수 있다.
 
- 아래와 같이 파라미터를 이용할 수 있다.
 
 
@PreAuthorize("#username == authentication.principal.username")
public String getMyRoles(String username){
    //...
}
@PostAuthorize("returnObject.username == authentication.principal.nickname")
public CustomUser loadUserDetail(String username){
    return userRoleRepository.loadUserByUserName(username);
}
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected AccessDecisionManager accessDecisionManager() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        AffirmativeBased accessDecisionManager = (AffirmativeBased) super.accessDecisionManager();
        accessDecisionManager.getDecisionVoters().add(new RoleHierarchyVoter(roleHierarchy));
        return accessDecisionManager;
    }
}
- 웹용이 아닌 범용적(예를 들어 데스크톱)으로 사용할 configuration 정의
 
- Hierarchy 를 설정하기 위해서는 위와 같이 상속받아 메소드를 재정의하여 설정해준다.
 
테스트 코드 작성
- 아래와 같이 테스트 코드를 작성할 수 있다. (Junit 4)
 
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleServiceTest {
    @Autowired
    SampleService sampleService;
    @Autowired
    AccountService accountService;
    @Autowired
    AuthenticationManager authenticationManager;
    @Test
    public void dashboard() {
        // 계정을 생성
        Account account = new Account();
        account.setRole("USER");
        account.setUsername("jake");
        account.setPassword("123");
        accountService.createNew(account);
        UserDetails userDetails = accountService.loadUserByUsername("jake");
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDetails, "123");
        Authentication authentication = authenticationManager.authenticate(token);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        sampleService.dashboard();
    }
}
- 위의 코드를 실행시킬때, MethodSecurityConfig 를 정의해 주지 않았다면, null 포인트 에러가 발생한다.
 
- 그 이유는 웹을 통한 테스트가 아니기 때문이다. -> GlobalMethodSecurityConfiguration 를 상속한 config 파일을 정의해 줘야한다.
 
- 목 객체를 만드는 과정은 아래와 같이 @WithMockUser 로 대체할 수 있다.
 
@Test
@WithMockUser
public void dashboard(){
    sampleService.dashboard();
}
REFERENCES