2012-10-29 60 views
2

我有一個ListView由不同的片段組成,其中包含文本和鏈接(在另一個片段內)。根據列表視圖模型的狀態,鏈接可見。Wicket鏈接重播攻擊

爲了簡單起見,假設鏈接是可見的,取決於列表視圖模型的布爾字段,如果它是真的是可見的,否則不可見。

首先鏈接是可見的,我複製鏈接位置(加密),我等待我的模型改變(即布爾值爲false),並且在刷新頁面後鏈接消失。 (正確!)

如果我試圖在瀏覽器中返回URL(之前複製),我收到一個WicketRuntimeException,告訴我沒有找到該鏈接的偵聽器。

更完整的鏈接是一個片段內:

<wicket:fragment wicket:id="reservationRatingFragment"> 
    <li> 
     <div> 
      <img src="/img/good.png" /> 
     </div> 
     <p> 
      <a wicket:id="ratingGoodLink" href="#"> <wicket:message 
        key="messaging.reservation.rating.good" /> 
      </a> 
     </p> 
    </li> 
</wicket:fragment> 

當我說看不見我的意思是我設置的片段的標記容器如.setVisible(假);

這是怎麼發生的?我假設,如果我記得一個不再可見的鏈接,框架應該跳過它並刷新我目前正在使用的頁面(或將頁面重定向到基本頁面)。

例如,如果我複製鏈接並更改BasePage(例如轉到主頁),當我調用複製的URL時,仍會發生異常。

EDITED:

在第一片段:

嵌套片段(ReservationRatingFragment):

public ReservationRatingFragment(String id, String markupId,MarkupContainer markupContainer, Item item, Message msg) { 
     super(id, markupId, markupContainer, new Model<Message>(msg)); 
     /* Avoid render container */ 
     setRenderBodyOnly(true); 

     /* Load button components */ 
     Link<Void> ratingGoodLink = new Link<Void>("ratingGoodLink"){ 
      private static final long serialVersionUID = 1L; 

      @Override 
      public void onClick() { 
       processRating(ReservationEvaluationResult.GOOD); 
      } 
     }; 
     add(ratingGoodLink); 

     Link<Void> ratingBadLink = new Link<Void>("ratingBadLink"){ 
      private static final long serialVersionUID = 1L; 
      @Override 
      public void onClick() { 
       processRating(ReservationEvaluationResult.BAD); 
      } 
     }; 
     add(ratingBadLink); 
    } 

標記爲兩個片段:

<wicket:fragment wicket:id="messageFragment"> 
    Some content... 
    <!-- Here goes my fragment with link --> 
    <ul wicket:id="messageRatingContainer"> 
     <div wicket:id="messageRatingSection"></div> 
    </ul> 

    <wicket:fragment wicket:id="reservationRatingFragment"> 
     <li><div> 
       <img src="/img/messaging/good.png" /> 
      </div> 
      <p> 
       <a wicket:id="ratingGoodLink" href="#"> <wicket:message 
         key="messaging.reservation.rating.good" /> 
       </a> 
      </p></li> 
     <li><div> 
       <img src="/img/messaging/bad.png" /> 
      </div> 
      <p> 
       <a wicket:id="ratingBadLink" href="#"> <wicket:message 
         key="messaging.reservation.rating.bad" /> 
       </a> 
      </p></li> 
    </wicket:fragment> 
</wicket:fragment> 

EDIT ED: processRating只是調用一個控制器(處理後端變化)。在控制器中,我檢查重播攻擊(如果這個動作已經被執行),如果是的話,我會拋出一個運行時異常,導致用戶到一個警告頁面(您已經評估過這條信息)。事實是,在這種情況下,它沒有到達這一點,因爲鏈接不可用,它不會調用控制器,並且它只是拋出InvalidUrlException,因爲鏈接不可見。

檢票版本:1.4.19

感謝

+0

這將有助於看到,除了HTML標記您的Java代碼。你在使用BookmarkablePageLink嗎? – OnesAndZeros

+0

我已經添加了一些代碼,我沒有使用任何BookmarkablePageLink,只是org.apache.wicket.markup.html.link.Link – Wizche

回答

1

唯一可行的解​​決方案,我發現是延長RequestCycle並重寫onRuntimeException方法是這樣的:

@Override 
public Page onRuntimeException(Page page, RuntimeException e) {  
    if(e instanceof InvalidUrlException) { 
     return new HomePage(); 
    } else { 
     return super.onRuntimeException(page, e); 
    } 
} 
+0

這個解決方案沒有什麼問題。 – biziclop

1

我不知道我理解你的執行的確切原因。也就是說,我建議使用帶有PageParameters的BookmarkablePageLink()集,以在加載目標頁面時執行processRating()方法。

添加你的鏈接部件:

PageParameters ppGood = new PageParameters("0="+ReservationEvaluationResult.GOOD); 
    PageParameters ppBad = new PageParameters("0="+ReservationEvaluationResult.BAD); 
    add(new BookmarkablePageLink("ratingGoodLink", DestinationPage.class, ppGood)); 
    add(new BookmarkablePageLink("ratingBadLink", DestinationPage.class, ppBad)); 

然後創建一個在您DestinationPage一個新的構造:

public class DestinationPage extends WebPage { 
    public DestinationPage(PageParameters param) { 
     if(param.getString("0")!=null){ 
      String rating = param.getString("0"); 
      processRating(rating); 
     } 
    ... 

這會給你一個鏈接,這將是持久的,應該讓你複製和粘貼網址。

+0

這不完全是我需要的,我只想避免用戶重試張貼舊鏈接地址。我看到的一個解決方案是在我的RequestCycle的onRuntimeException中捕獲InvalidUrlException,但它聽起來並不正確。 – Wizche

5

您認爲無效鏈接將被忽略或將您重定向到基頁是錯誤的。

這是爲什麼?

如果我們退後一步,點擊鏈接會發生什麼?您的應用程序狀態發生變化。但是,如果應用程序處於鏈接創建時的狀態,則這樣做是安全的。如果這條規則沒有被強制執行,那麼您需要確保每一個潛在的狀態轉換都可以接受或明確標記爲無效。這在大多數系統中即使不是不可能也是非常不切實際的。但忽視這一點不僅會帶來安全風險,而且會導致數據的損壞。

最好把它看作樂觀鎖定的例子。 (主要是因爲:))創建鏈接時,創建時會給出內部狀態的版本號。點擊鏈接時,該版本號將與內部狀態的當前版本進行比較。如果兩者匹配,則鏈接被接受爲有效,內部狀態被更新並且其版本號增加。如果兩個數字不匹配,則鏈接被拒絕並拋出異常,因爲無法忽略無效的狀態轉換嘗試。

我不會解釋如何解決這個限制,因爲它已經在另一個答案中被告知,我只是想回答「爲什麼」的問題。