我一直在努力解决这个问题。我想对ActionBean
和show
操作使用相同的条带update
。但是,我无法弄清楚如何以一种干净的方式做到这一点,它允许当前用户可靠地绑定,验证和验证对象所有权。
例如,假设我们的action bean需要postingId
。该帖子属于已登录的用户。我们可能会这样:
@UrlBinding("/posting/{postingId}")
@RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
现在,对于show
操作,我们可以定义:
private int postingId; // assume the parameter in @UrlBinding above was renamed
private Posting posting;
现在使用@After(stages = LifecycleStage.BindingAndValidation)
来获取Posting
。我们的@After
函数可以验证当前登录的用户是否拥有该帖子。我们必须使用@After
,而不是@Before
,因为postingId
之前不会绑定参数。
但是,对于update
函数,您希望使用Posting
而不是@Before
将@After
对象绑定到发布变量,以便返回的表单条目获得应用于现有Posting对象的顶部,而不是应用于空的存根。
自定义TypeConverter<T>
在这里可以正常运行,但由于TypeConverter
界面无法提供会话,因此在绑定过程中难以验证对象的所有权。
我能看到的唯一解决方案是使用两个单独的动作bean,一个用于show,另一个用于更新。但是,如果您执行此操作,<stripes:form>
标记及其下游标记将无法正确填充表单的值,因为beanclass
或action
标记必须映射回相同的{{ 1}}。
据我所知,Stripes模型仅在操作简单(无POJO)参数时保持在一起。在任何其他情况下,您似乎遇到了从数据存储中绑定对象并使用客户端发送的更新覆盖它的catch-22。
我必须遗漏一些东西。经验丰富的Stripes用户的最佳实践是什么?
答案 0 :(得分:1)
在我看来,授权与对象水合正交。通过这个,我的意思是你应该将对象水合作用的关注点(在这种情况下,使用postingId
并将其转换为Posting
)而不是确定用户是否有权对其执行操作对象(如show,update,delete等)。
对于对象保湿,我使用TypeConverter<T>
,并且我在不考虑会话用户的情况下保湿对象。然后在我的ActionBean
里面我有一个守护者,因此......
public void setPosting(Posting posting) {
if (accessible(posting)) this.posting = posting;
}
其中accessible(posting)
看起来像这样......
private boolean accessible(Posting posting) {
return authorisationChecker.isAuthorised(whoAmI(), posting);
}
然后您的show()
事件方法看起来像这样......
public Resolution show() {
if (posting == null) return NOT_FOUND;
return new ForwardResolution("/WEB-INF/jsp/posting.jsp");
}
另外,当我使用Stripes时,我经常在同一条纹ActionBean
中有多个事件(如“show”或“update”)。对我来说,围绕相关名词对操作(动词)进行分组是有意义的。
使用干净的网址,您的ActionBean
注释将如下所示......
@UrlBinding("/posting/{$event}/{posting}")
@RolesAllowed({ "USER" })
public class PostingActionBean extends BaseActionBean
...其中{$event}
是您的事件方法的名称(即“show”或“update”)。请注意,我使用的是{posting}
,而不是{postingId}
。
为了完整性,以下是您的update()
事件方法的样子......
public Resolution update() {
if (posting == null) throw new UnauthorisedAccessException();
postingService.saveOrUpdate(posting);
message("posting.save.confirmation");
return new RedirectResolution(PostingsAction.class);
}