簡體   English   中英

Spring Spring中的Spring表達式語言(SpEL)比較對象使用equals()或==?

[英]Spring Expression Language (SpEL) in Spring Security to compare object use equals() or ==?

Spring Spring中的Spring表達式語言(SpEL)比較對象使用equals()或==?

例如(方法equals()未被調用!):

class SecurityObject {      
   public boolean equals(Object obj) {
  //...
   }
 }

@PreAuthorize(" #secObject == #otherSecObject ") 
public void securityMethod(SecurityObject secObject, SecurityObject otherSecObject) {                        
   //...        
}

這個是正常的!? 我需要到處使用@PreAuthorize(“#secObject.equals(#otherSecObject)”)?

UPDATE

為什么在第一種情況下Spring Security調用.equals(),第二種情況不是?

      //TestObject 

      public class TestObject {

      private static final Logger log = LoggerFactory.getLogger(TestObject.class);

      private Long id;

      public TestObject(Long id) {
           this.id = id;
      }

       @Override
       public int hashCode() {
           int hash = 7;
           hash = 71 * hash + Objects.hashCode(this.id);
           return hash;
       }

       @Override
       public boolean equals(Object obj) {

       log.info("equals");

       if (obj == null) {
          return false;
       }

       if (getClass() != obj.getClass()) {
         return false;
       }
       final TestObject other = (TestObject) obj;
       if (!Objects.equals(this.id, other.id)) {
         return false;
       }
      return true;
  }               
}

//TestService

@PreAuthorize(" #one == #two ")
public String testEqualsInAnnotation(Long one, Long two) {        
    //...
}

@Override
@PreAuthorize(" #one == #two ")
public String testEqualsInAnnotation(TestObject one, TestObject two) {
    //...
}

//Test

    log.info("for Long");
    Long one = new Long(500);
    Long two = new Long(500);        

    log.info("one == two: {}", (one==two)? true : false); // print false
    log.info("one equals two: {}", (one.equals(two))? true : false); // print true

    testService.testEqualsInAnnotation(one, two); //OK

    log.info("for TestObject");

    TestObject oneObj = new TestObject(new Long(500));
    TestObject twoObj = new TestObject(new Long(500));              

    log.info("oneObj == twoObj: {}", (oneObj==twoObj)? true : false); // print false
    log.info("oneObj equals twoObj: {}", (oneObj.equals(twoObj))? true : false); // print true

    testService.testEqualsInAnnotation(oneObj, twoObj); // AccessDeniedException: Access is denied

更新2

equals()從未被調用過

           package org.springframework.expression.spel.ast;

           import org.springframework.expression.EvaluationException;
           import org.springframework.expression.spel.ExpressionState;
           import org.springframework.expression.spel.support.BooleanTypedValue;

/**
 * Implements equality operator.
 *
 * @author Andy Clement
 * @since 3.0
 */
public class OpEQ extends Operator {

    public OpEQ(int pos, SpelNodeImpl... operands) {
        super("==", pos, operands);
    }

    @Override
    public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
        Object left = getLeftOperand().getValueInternal(state).getValue();
        Object right = getRightOperand().getValueInternal(state).getValue();
        if (left instanceof Number && right instanceof Number) {
            Number op1 = (Number) left;
            Number op2 = (Number) right;
            if (op1 instanceof Double || op2 instanceof Double) {
                return BooleanTypedValue.forValue(op1.doubleValue() == op2.doubleValue());
            } else if (op1 instanceof Long || op2 instanceof Long) {
                return BooleanTypedValue.forValue(op1.longValue() == op2.longValue());
            } else {
                return BooleanTypedValue.forValue(op1.intValue() == op2.intValue());
            }
        }
        if (left!=null && (left instanceof Comparable)) {
            return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) == 0);
        } else {
            return BooleanTypedValue.forValue(left==right);
        }
    }

}

根據spEL文檔,您需要創建ExpressionParser實例,創建一個Expression實例並獲取如下所示的值

String name = "Nikola Tesla";
Expression exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(Boolean.class); 

結果評估為'true'。 這表示當我們需要比較任何兩個對象時,我們需要覆蓋equals()方法並將兩個對象傳遞給解析器#parseExpression(“obj1 == obj2”),然后調用exp#getValue(Boolean.class)來評估。 以類似的方式,Expression實例也可以包含包含Obj1.equals(Obj2)表達式字符串,用於檢查相等性。 因此,使用spEL可以實現檢查相等性的方法。

rdm,我認為你必須使用權限評估程序來評估表達式。 我認為您沒有為下面的表達式中的對象注入/傳遞值。

@Override
@PreAuthorize(" #one == #two ")
public String testEqualsInAnnotation(TestObject one, TestObject two) {
    //...

我試圖做同樣的事情,但我沒有傳遞值,因此無法評估表達式。 我的建議是為上面的表達式實現自定義權限評估程序,並從求值程序中注入/傳遞值。 為了概括我的想法,我的懷疑是對象是null,這就是為什么你無法評估它。 如果你真的可以在這里傳遞對象的值,請告訴我們: @PreAuthorize(" #one == #two ")

Added:

我正在使用權限評估程序來評估@PreAuthorize(...)注釋下的表達式。 因為我無法將值傳遞給參數,如上所述。 如果可以傳遞/注入值,那么降低使用權限評估程序可能帶來的復雜性將是很好的。

rdm或其他人,你能指點我如何在@PreAuthorize(...)下傳遞參數值嗎?

很抱歉在rdm的帖子上提出另一個問題,並提前感謝您的幫助!

您可能已經發現了這個,因為它位於原始帖子的“Update 2”中的OpEq代碼中,但是......

比較運算符lt < gt > le <= ge >= eq == ne !=基於java的Comparable接口。

因此,如果您希望能夠在SpEL表達式中使用==!=進行比較,那么您可以編寫它以實現Comparable 當然,那么你必須找出一些合理的規則,以確定哪個對象在它們之前是不相等的。

也就是說,我在Spring的當前文檔中找不到任何指示這一點的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM