【问题标题】:Wicket link replay attackWicket 链接重放攻击
【发布时间】:2012-10-19 00:27:01
【问题描述】:

我有一个由不同片段组成的 ListView,其中包含文本和链接(在另一个片段内)。根据列表视图模型的状态,链接是否可见。

为简单起见,假设链接是否可见,具体取决于列表视图模型的布尔字段,如果为真则可见,否则不可见。

最初链接是可见的,我复制链接位置(加密),等待模型更改(即布尔值变为 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(false);

为什么会这样?我假设如果我想起一个不再可见的链接,框架应该跳过它并刷新我当前所在的页面(或将我重定向到基本页面)。

例如,如果我复制了链接并更改了 BasePage(例如转到主页),则当我调用复制的 URL 时仍然会发生异常。

编辑:

在第一个片段中:

WebMarkupContainer msgRatingContainer = new WebMarkupContainer("messageRatingContainer") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onConfigure() {
                setVisible(message.getType() == MessageType.RATING);
            }
        };

if (msgRatingContainer.isVisible()) {
            if (message.getType() == MessageType.RATING) {
                msgRatingContainer.add(new ReservationRatingFragment("messageRatingSection",
                        "reservationRatingFragment", this, item, message));
}

嵌套片段(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>

编辑: processRating 只是调用一个控制器(它处理后端的变化)。在控制器中,我检查重放攻击(如果已执行此操作),如果是,则抛出运行时异常,将用户引导至警告页面(您已对此消息进行评级)。事实是,在这种情况下,它没有达到这一点,因为链接不可用,它不会调用控制器,它只是抛出 InvalidUrlException,因为链接不可见。

检票口版本:1.4.19

谢谢

【问题讨论】:

  • 除了 html 标记之外,查看您的 Java 代码也会有所帮助。你在使用 BookmarkablePageLink 吗?
  • 我添加了更多代码,我不使用任何 BookmarkablePageLink,只使用 org.apache.wicket.markup.html.link.Link

标签: java exception hyperlink wicket replay


【解决方案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);
        }
     ...

这将为您提供一个永久链接,并允许您复制和粘贴 URL。

【讨论】:

  • 这不是我所需要的,我只是想避免用户重试发布旧链接地址。我看到的一种解决方案是在我的 RequestCycle 的 onRuntimeException 中捕获 InvalidUrlException,但这对我来说并不正确。
【解决方案2】:

您认为无效链接将被忽略或将您重定向到基本页面的假设是错误的。

这是为什么呢?

如果我们退后一步,当您点击链接时会发生什么?应用程序的状态发生变化。但是,只有当应用程序处于创建链接时的状态时,这样做才是安全的。如果未强制执行此规则,则您需要确保每个潜在的状态转换都是可接受的或明确标记为无效。在大多数系统中,如果不是不可能的话,这将是非常不切实际的。但忽视这一点不仅会带来安全风险,而且可能导致数据损坏。

最好将其视为乐观锁定的情况。 (多半是因为是 :)) 创建链接的时候,会给出创建时内部状态的版本号。单击链接时,该版本号将与内部状态的当前版本进行比较。如果两者匹配,则链接被接受为有效,更新内部状态并增加其版本号。如果两个数字不匹配,则链接将被拒绝并抛出异常,因为无法忽略无效的状态转换尝试。

我不会解释如何绕过这个限制,因为它已经在另一个答案中被告知,我只是想回答“为什么”的问题。

【讨论】:

    【解决方案3】:

    我发现唯一可行的解​​决方案是扩展 RequestCycle 并以这种方式覆盖 onRuntimeException 方法:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-15
      • 2013-08-22
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多