복붙노트

[SPRING] Spring 어노테이션에서 정적 변수 사용하기

SPRING

Spring 어노테이션에서 정적 변수 사용하기

Spring의 PreAuthorize 주석을 다음과 같이 사용하고 있습니다.

@PreAuthorize("hasRole('role')");

그러나 이미 다른 클래스의 정적 String으로 정의 된 '역할'이 있습니다. 이 값을 사용하려고하면 :

@PreAuthorize("hasRole(OtherClass.ROLE)");

오류가 발생했습니다.

org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 14): Field or property 'OtherClass' cannot be found on object of type 'org.springframework.security.access.expression.method.MethodSecurityExpressionRoot'

PreAuthorize 주석을 사용하여 정적 변수에 액세스하는 방법이 있습니까?

해결법

  1. ==============================

    1.Spring Expression Language를 사용하여 유형을 평가하는 다음을 시도해보십시오.

    Spring Expression Language를 사용하여 유형을 평가하는 다음을 시도해보십시오.

    @PreAuthorize("hasRole(T(fully.qualified.OtherClass).ROLE)");
    

    정규화 된 클래스 이름을 지정해야합니다.

    선적 서류 비치

  2. ==============================

    2.패키지 이름없이 표현식을 작성할 수있게하려면 다음을 수행하십시오.

    패키지 이름없이 표현식을 작성할 수있게하려면 다음을 수행하십시오.

    <sec:global-method-security>
        <sec:expression-handler ref="methodSecurityExpressionHandler"/>
    </sec:global-method-security>
    
    <bean id="methodSecurityExpressionHandler" class="my.example.DefaultMethodSecurityExpressionHandler"/>
    

    그런 다음 DefaultMethodSecurityExpressionHandler를 확장합니다.

    public class DefaultMethodSecurityExpressionHandler extends org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler {
    
        @Override
        public StandardEvaluationContext createEvaluationContextInternal(final Authentication auth, final MethodInvocation mi) {
            StandardEvaluationContext standardEvaluationContext = super.createEvaluationContextInternal(auth, mi);
            ((StandardTypeLocator) standardEvaluationContext.getTypeLocator()).registerImport("my.example");
            return standardEvaluationContext;
        }
    }
    

    이제 my.example.Roles.java를 만듭니다.

    public class Roles {
    
        public static final String ROLE_UNAUTHENTICATED = "ROLE_UNAUTHENTICATED";
    
        public static final String ROLE_AUTHENTICATED = "ROLE_AUTHENTICATED";
    }
    

    주석에 패키지 이름없이 참조하십시오.

    @PreAuthorize("hasRole(T(Roles).ROLE_AUTHENTICATED)")
    

    대신에:

    @PreAuthorize("hasRole(T(my.example.Roles).ROLE_AUTHENTICATED)")
    

    더 읽기 쉬워졌습니다. 또한 역할이 입력됩니다. 쓰다:

    @PreAuthorize("hasRole(T(Roles).ROLE_AUTHENTICATEDDDD)")
    

    그리고 당신이 쓴다면 거기에 없었을 시작 오류가 발생합니다 :

        @PreAuthorize("hasRole('ROLE_AUTHENTICATEDDDD')")
    
  3. ==============================

    3.Kevin Bowersox의 대답이 받아 들여지지 만 T (fully.qualified.path) 물건을 가지고있는 것을 좋아하지 않으므로 계속보고 있습니다. 제임스 왓킨스 (James Watkins)의 답변을 사용하여 사용자 지정 보안 방법을 작성했습니다.

    Kevin Bowersox의 대답이 받아 들여지지 만 T (fully.qualified.path) 물건을 가지고있는 것을 좋아하지 않으므로 계속보고 있습니다. 제임스 왓킨스 (James Watkins)의 답변을 사용하여 사용자 지정 보안 방법을 작성했습니다.

    스프링 보안 표현식 언어 주석에 사용할 사용자 정의 메소드를 작성하는 방법

    그러나 String 대신 매개 변수 유형으로 enums.Permissions 클래스를 사용했습니다.

    @Component
    public class MySecurityService {
        public boolean hasPermission(enums.Permissions permission) {
    
            ...do some work here...
    
            return true;
        }
    }
    

    이제 깔끔한 부분은 주석에서 hasPermission을 호출 할 때 전체 경로를 입력 할 필요가 없지만 작은 따옴표로 묶어야한다는 것입니다.

    @PreAuthorize("@mySecurityService.hasPermission('SOME_ROLE_NAME')")
    

    hasPermission 메소드는 Enum을 기대하기 때문에, 자동적으로 그 이름을 가지는 Enum 값을 찾습니다. 찾지 못하면 예외가 발생합니다.

    org.springframework.expression.spel.SpelEvaluationException: Type conversion problem, cannot convert from java.lang.String to enums.Permissions
    

    hasPermission의 이름을 hasRole로 변경할 수 있습니다.이 경우 트레이드 오프는 @mySecurityService 및 추가 작은 따옴표에 대해 T (fully.qualified.path)를 거래하는 것입니다.

    그것이 더 좋을 지 확실하지 않지만 거기에 있습니다. 어쨌든 컴파일 타임에 값을 검증하지 않으므로 다음 단계는 주석 프로세서를 만드는 것입니다.

    봄이 자동으로 열거 형으로 변환 될 수 있다는 것을 지적하기 위해 krosenvold에게도 크레딧을 주어야합니다. https://stackoverflow.com/a/516899/618881

  4. ==============================

    4.다음과 같이 시도해보십시오.

    다음과 같이 시도해보십시오.

    @PreAuthorize("hasRole(T(com.company.enumpackage.OtherClass).ROLE.name())");
    

    OtherClass 열거 형을 public static으로 선언하면 $ sign을 사용해야합니다.

    @PreAuthorize("hasRole(T(com.company.ParentTopLevelClass$OtherClass).ROLE.name())");
    

    나중에 toString ()을 재정의하는 경우 향후 문제를 방지하기 위해 name ()

  5. from https://stackoverflow.com/questions/17444856/using-static-variables-in-spring-annotations by cc-by-sa and MIT license