2013-07-03 40 views
10

Tôi đang sử dụng giai đoạn này Tổng chú thích mùa xuân như sau:Sử dụng các biến tĩnh trong chú thích mùa xuân

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

Tuy nhiên, tôi đã có 'vai trò' định nghĩa là một String tĩnh trên lớp khác. Nếu tôi cố gắng sử dụng giá trị này:

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

tôi nhận được một lỗi:

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' 

Có cách nào để truy cập các biến tĩnh như thế này với một chú thích sẵn trong giai đoạn?

Trả lời

16

Hãy thử những điều sau đây trong đó sử dụng mùa xuân Expression Language để đánh giá các loại:

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

Hãy chắc chắn để xác định tên lớp đầy đủ.

Documentation

+0

Các công trình lớn, cảm ơn bạn! – RobEarl

+0

@RobEarl Awesome Glad Tôi có thể giúp. Tôi cũng học được điều gì đó. –

+0

Hoạt động, nhưng nó vẫn là một chuỗi diễn giải, vì vậy nó sẽ không được "nhìn thấy" bởi Eclipse khi bạn refactor ví dụ. tên tôi đoán. – yglodt

3

Hãy thử một cái gì đó như thế này:

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

Nếu enum OtherClass của bạn được khai báo là public static, thì bạn cần phải sử dụng $ dấu:

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

name() để ngăn chặn futer vấn đề nếu toString() sẽ bị ghi đè sau

4

Câu trả lời được chấp nhận từ Kevin Bowersox hoạt động, nhưng tôi không thích có công cụ T (fully.qualified.path) để tôi tiếp tục tìm kiếm. Tôi bắt đầu bằng cách tạo ra một phương thức bảo mật tùy chỉnh bằng cách sử dụng câu trả lời từ James Watkins ở đây:

How to create custom methods for use in spring security expression language annotations

Tuy nhiên, thay vì một String, tôi đã sử dụng lớp enums.Permissions của tôi như là một tham số kiểu:

@Component 
public class MySecurityService { 
    public boolean hasPermission(enums.Permissions permission) { 

     ...do some work here... 

     return true; 
    } 
} 

Bây giờ phần gọn gàng là khi tôi gọi hasPermission từ một chú thích, tôi không phải gõ toàn bộ đường dẫn, nhưng tôi phải kèm theo nó trong dấu nháy đơn:

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

Bởi vì phương thức hasPermission mong đợi một Enum, nó sẽ tự động tìm giá trị Enum với tên đó. Nếu nó không tìm thấy nó, bạn sẽ nhận được một ngoại lệ:

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

Bạn có thể đổi tên hasPermission để hasRole, trong trường hợp mà việc buôn bán chỉ ra là bạn đang kinh doanh T (fully.qualified.path) cho @mySecurityService và thêm dấu nháy đơn.

Không chắc nó có tốt hơn hay không, nhưng đúng vậy. Vì không có điều nào trong số này sẽ xác minh các giá trị tại bất kỳ thời gian biên dịch nào, bước tiếp theo của tôi là tạo một bộ xử lý chú thích.

Tôi cũng phải cung cấp tín dụng để krosenvold để chỉ ra mùa xuân có thể tự động chuyển đổi sang một enum: https://stackoverflow.com/a/516899/618881

6

Để làm cho nó có thể viết các biểu thức mà không cần tên gói:

<sec:global-method-security> 
    <sec:expression-handler ref="methodSecurityExpressionHandler"/> 
</sec:global-method-security> 

<bean id="methodSecurityExpressionHandler" class="my.example.DefaultMethodSecurityExpressionHandler"/> 

Sau đó mở rộng the 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; 
    } 
} 

Bây giờ tạo my.example.Roles.java:

public class Roles { 

    public static final String ROLE_UNAUTHENTICATED = "ROLE_UNAUTHENTICATED"; 

    public static final String ROLE_AUTHENTICATED = "ROLE_AUTHENTICATED"; 
} 

Và đề cập đến nó mà không có tên gói trong các chú thích:

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

thay vì:

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

Làm cho nó dễ đọc hơn IMHO. Ngoài ra, vai trò hiện đã được nhập. Viết:

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

và bạn sẽ nhận được lỗi khởi động mà sẽ không có được ở đó nếu bạn đã viết:

@PreAuthorize("hasRole('ROLE_AUTHENTICATEDDDD')") 
+0

Giải pháp tốt. Có lỗi khởi động sẽ tốt đẹp, nhưng tôi không nghĩ rằng bạn có thể đạt được điều đó như thế này. Việc đánh giá vẫn xảy ra trong thời gian chạy. Đã không tìm thấy một giải pháp tốt hơn nhưng khó khăn ... – chris

Các vấn đề liên quan