스프링 보안 표현 언어 주석에서 사용할 사용자 지정 메서드를 만드는 방법
주석을 통한 메서드 기반 인증을 위해 스프링 보안 표현 언어에서 사용할 사용자 지정 메서드를 추가하는 클래스를 만들고 싶습니다.
예를 들어 다음과 같이 사용되는 'customMethodReturningBoolean'과 같은 사용자 지정 메서드를 만들고 싶습니다.
@PreAuthorize("customMethodReturningBoolean()")
public void myMethodToSecure() {
// whatever
}
제 질문은 이것입니다. 가능하다면 사용자 지정 메서드를 생성하기 위해 어떤 클래스를 하위 클래스로 지정해야합니까? 스프링 xml 구성 파일에서 구성하는 방법에 대해 설명하고 누군가 이러한 방식으로 사용되는 사용자 지정 메서드의 예를 제공 할 수 있습니까?
두 개의 클래스를 하위 클래스로 분류해야합니다.
먼저 새 메서드 표현식 핸들러를 설정합니다.
<global-method-security>
<expression-handler ref="myMethodSecurityExpressionHandler"/>
</global-method-security>
myMethodSecurityExpressionHandler
의 하위 클래스 DefaultMethodSecurityExpressionHandler
를 재정의 createEvaluationContext()
하는 하위 클래스가 MethodSecurityExpressionRoot
됩니다 MethodSecurityEvaluationContext
.
예를 들면 :
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth);
root.setTrustResolver(trustResolver);
root.setPermissionEvaluator(permissionEvaluator);
root.setRoleHierarchy(roleHierarchy);
ctx.setRootObject(root);
return ctx;
}
언급 된 기술 중 어느 것도 더 이상 작동하지 않습니다. Spring은 사용자가 SecurityExpressionRoot를 재정의하는 것을 방지하기 위해 많은 노력을 기울인 것처럼 보입니다.
11/19/14 설정 Spring을 수정하여 보안 주석을 사용하십시오.
<beans ... xmlns:sec="http://www.springframework.org/schema/security" ... >
...
<sec:global-method-security pre-post-annotations="enabled" />
다음과 같이 빈을 만듭니다.
@Component("mySecurityService")
public class MySecurityService {
public boolean hasPermission(String key) {
return true;
}
}
그런 다음 jsp에서 다음과 같이하십시오.
<sec:authorize access="@mySecurityService.hasPermission('special')">
<input type="button" value="Special Button" />
</sec:authorize>
또는 메소드에 주석을 추가하십시오.
@PreAuthorize("@mySecurityService.hasPermission('special')")
public void doSpecialStuff() { ... }
또한 주석 에서 Spring Expression Language@PreAuthorize
를 사용하여 현재 인증 및 메소드 인수에 액세스 할 수 있습니다 .
예를 들면 :
@Component("mySecurityService")
public class MySecurityService {
public boolean hasPermission(Authentication authentication, String foo) { ... }
}
그런 다음 @PreAuthorize
새 메소드 서명과 일치하도록 업데이트하십시오 .
@PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)")
public void doSpecialStuff(String foo) { ... }
감사합니다 ericacm ,하지만 몇 가지 이유로 작동하지 않습니다.
- DefaultMethodSecurityExpressionHandler 의 속성 은 비공개입니다 (반사 가시성 kludges 바람직하지 않음)
- At least in my Eclipse, I can't resolve a MethodSecurityEvaluationContext object
The differences are that we call the existing createEvaluationContext method and then add our custom root object. Finally I just returned an StandardEvaluationContext object type since MethodSecurityEvaluationContext would not resolve in the compiler (they are both from the same interface). This is the code that I now have in production.
Make MethodSecurityExpressionHandler use our custom root:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
// parent constructor
public CustomMethodSecurityExpressionHandler() {
super();
}
/**
* Custom override to use {@link CustomSecurityExpressionRoot}
*
* Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
* configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.
*/
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
// due to private methods, call original method, then override it's root with ours
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );
return ctx;
}
}
This replaces the default root by extending SecurityExpressionRoot. Here I've renamed hasRole to hasEntitlement:
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
// parent constructor
public CustomSecurityExpressionRoot(Authentication a) {
super(a);
}
/**
* Pass through to hasRole preserving Entitlement method naming convention
* @param expression
* @return boolean
*/
public boolean hasEntitlement(String expression) {
return hasRole(expression);
}
}
Finally update securityContext.xml (and make sure it's referenced from your applcationContext.xml):
<!-- setup method level security using annotations -->
<security:global-method-security
jsr250-annotations="disabled"
secured-annotations="disabled"
pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<!--<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">-->
<bean id="expressionHandler" class="com.yourSite.security.CustomMethodSecurityExpressionHandler" />
Note: the @Secured annotation will not accept this override as it runs through a different validation handler. So, in the above xml I disabled them to prevent later confusion.
'programing tip' 카테고리의 다른 글
불법 배포로부터 소프트웨어를 어떻게 보호합니까? (0) | 2020.09.09 |
---|---|
전략 패턴의 실제 사례 (0) | 2020.09.09 |
구성 파일 당 하나의 configSections 요소 만 허용되며 존재하는 경우 루트 구성 요소의 첫 번째 하위 요소 여야합니다. (0) | 2020.09.09 |
Python 함수 호출에서 stdout 출력을 캡처하는 방법은 무엇입니까? (0) | 2020.09.09 |
프로젝트 기타 파일에 대한 NuGet 패키지 복원 실패 : 값은 null이거나 빈 문자열 일 수 없습니다. (0) | 2020.09.09 |