[SPRING] Spring Security @ PreAuthorize / @ PostAuthorize 어노테이션에서 커스텀 표현식을 사용하는 방법
SPRINGSpring Security @ PreAuthorize / @ PostAuthorize 어노테이션에서 커스텀 표현식을 사용하는 방법
@Preauthorize 블록에서보다 풍부한 표현 문을 작성하는 방법이 있습니까? @Preauthorize가 매우 똑똑하지 않기 때문에 반복되는 것을 발견하는 예가 있습니다.
@RequestMapping(value = "{id}", method = RequestMethod.DELETE)
public void deleteGame(@PathVariable int id, @ModelAttribute User authenticatingUser) {
Game currentGame = gameService.findById(id);
if(authenticatingUser.isAdmin() || currentGame.getOwner().equals(authenticatingUser)) {
gameService.delete(gameService.findById(id));
} else {
throw new SecurityException("Only an admin, or an owner can delete a game.");
}
}
내가 좋아할만한 것이 있습니다.
@RequestMapping(value = "{id}", method = RequestMethod.DELETE)
@Preauthorize(isAdmin(authenicatingUser) OR isOwner(authenicatingUser, id)
public void deleteGame(@PathVariable int id, @ModelAttribute User authenticatingUser, @ModelAttribute currentGame ) { //I'm not sure how to add this either :(
gameService.delete(gameService.findById(id));
}
문제의 일부는 데이터베이스에 질의하여 게임 복사본을 얻은 다음이 게임 소유자를 제작자와 비교하는 것과 같이 사용 권한을 확인하기 위해이 물건 중 일부를 가져 오기 위해 데이터베이스에 쿼리를해야한다는 것입니다. 요청. 나는 모든 것이 어떻게 @Preauthorize 주석 처리기의 컨텍스트 내에서 작동하는지, 또는 @Preauthorize ( "") 값 속성에서 사용 가능한 객체 컬렉션에 어떤 것을 추가하는지에 대해 잘 모르겠습니다.
해결법
-
==============================
1.1) 먼저 메서드 별 기능이 추가 된 MethodSecurityExpressionRoot를 다시 구현해야합니다. 최초의 스프링 시큐리티 구현은 private 패키지이므로 확장하기 만 할 수는 없습니다. 주어진 클래스의 소스 코드를 확인하는 것이 좋습니다.
1) 먼저 메서드 별 기능이 추가 된 MethodSecurityExpressionRoot를 다시 구현해야합니다. 최초의 스프링 시큐리티 구현은 private 패키지이므로 확장하기 만 할 수는 없습니다. 주어진 클래스의 소스 코드를 확인하는 것이 좋습니다.
public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations { // copy everything from the original Spring Security MethodSecurityExpressionRoot // add your custom methods public boolean isAdmin() { // do whatever you need to do, e.g. delegate to other components // hint: you can here directly access Authentication object // via inherited authentication field } public boolean isOwner(Long id) { // do whatever you need to do, e.g. delegate to other components } }
2) 다음으로 위에 정의 된 CustomMethodSecurityExpressionRoot를 사용할 사용자 지정 MethodSecurityExpressionHandler를 구현해야합니다.
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); @Override public void setReturnObject(Object returnObject, EvaluationContext ctx) { ((MethodSecurityExpressionRoot) ctx.getRootObject().getValue()).setReturnObject(returnObject); } @Override protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) { final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication); root.setThis(invocation.getThis()); root.setPermissionEvaluator(getPermissionEvaluator()); root.setTrustResolver(this.trustResolver); root.setRoleHierarchy(getRoleHierarchy()); return root; } }
3) 컨텍스트에서 표현식 핸들러 빈을 정의한다. XML을 통해 다음과 같이 할 수 있습니다.
<bean id="methodSecurityExpressionHandler" class="my.package.CustomMethodSecurityExpressionHandler"> <property name="roleHierarchy" ref="roleHierarchy" /> <property name="permissionEvaluator" ref="permissionEvaluator" /> </bean>
4) 위의 정의 된 핸들러 등록
<security:global-method-security pre-post-annotations="enabled"> <security:expression-handler ref="methodSecurityExpressionHandler"/> </security:global-method-security>
5) 그런 다음 @PreAuthorize 및 / 또는 @PostAuthorize 주석에서 정의 된 표현식을 사용하십시오.
@PreAuthorize("isAdmin() or isOwner(#id)") public void deleteGame(@PathVariable int id, @ModelAttribute currentGame) { // do whatever needed }
그리고 한 가지 더. 컨트롤러 메소드를 보호하기 위해 메소드 레벨 보안을 사용하는 것이 아니라 비즈니스 로직 (예 : 서비스 계층 메소드)을 사용하여 메소드를 보안하는 것이 일반적입니다. 그런 다음 아래와 같이 사용할 수 있습니다.
public interface GameService { // rest omitted @PreAuthorize("principal.admin or #game.owner = principal.username") public void delete(@P("game") Game game); }
그러나 이것은 단지 하나의 예에 불과하다는 것을 명심하십시오. 실제 주체에 isAdmin () 메서드가 있고 게임에 소유자의 사용자 이름을 반환하는 getOwner () 메서드가 있다고 예상합니다.
-
==============================
2.@PreAuthorize가 SpEl 표현식을 평가하기 때문에, 가장 쉬운 방법은 단지 콩을 가리키는 것입니다 :
@PreAuthorize가 SpEl 표현식을 평가하기 때문에, 가장 쉬운 방법은 단지 콩을 가리키는 것입니다 :
@PreAuthorize("@mySecurityService.someFunction()")
MySecurityService.someFunction에는 반환 유형 boolean이 있어야합니다.
Spring 보안은 Authentication 객체를 전달하기를 원한다면 자동적으로 authentication이라는 변수를 제공 할 것이다. 유효한 SpEl 표현식을 사용하여 보안 메소드에 전달 된 모든 인수에 액세스하고, 정규 표현식을 평가하고, 정적 메소드를 호출 할 수 있습니다. 예 :
@PreAuthorize("@mySecurityService.someFunction(authentication, #someParam)")
-
==============================
3.다음과 같이 주석을 작성할 수 있습니다.
다음과 같이 주석을 작성할 수 있습니다.
@PreAuthorize("hasRole('ROLE_ADMIN') and hasPermission(#id, 'Game', 'DELETE')")
hasPermission 부분을 작동 시키려면 PermissionEvaluator 인터페이스를 구현해야합니다.
그런 다음 표현식 처리기 bean을 정의하십시오.
@Autowired private PermissionEvaluator permissionEvaluator; @Bean public DefaultMethodSecurityExpressionHandler expressionHandler() { DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); handler.setPermissionEvaluator(permissionEvaluator); return handler; }
보안 설정에 삽입하십시오.
<global-method-security pre-post-annotations="enabled"> <expression-handler ref="expressionHandler" /> </global-method-security>
from https://stackoverflow.com/questions/26747452/how-to-use-custom-expressions-in-spring-security-preauthorize-postauthorize-an by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 주석의 차이점 (0) | 2018.12.29 |
---|---|
[SPRING] 봄 콩 범위 (0) | 2018.12.29 |
[SPRING] 세션에서 Spring 저장 객체 (0) | 2018.12.29 |
[SPRING] Spring RestTemplate을 사용하여 Https Rest Service에 액세스 (0) | 2018.12.29 |
[SPRING] Spring 3.0 대 Java EE 6.0 [닫기] (0) | 2018.12.29 |