如何安全地使用URL GET请求参数初始化ViewScoped bean?

3

我有几个托管bean(ViewScoped),目前使用会话数据进行初始化。我想使用URL GET参数对它们进行初始化,以便在视图中提供要显示的实体ID的URL。类似于displayClient.xhtml?entityId=123

现在,在视图主实体的getter方法中,我正在考虑像这样的解决方案:

public clientModel getclientM() {
  if (this.clientM == null) {
    // TODO: Check for empty, non-integer or garbage parameters...
    // Anything exists to "sanitize" URL parameters?
    int entityId = Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("entityId"));

    // I guess I should check here if the logged user is authorized to 
    // load client entity with this entityId...  anything else to check?

    this.clientM = this.clientS.find(entityId);
  }

  return this.clientM;
}

任何最佳实践的提示或建议将不胜感激。

但是为什么呢?Bean 是在 HTTP 会话中管理的,而不是在 URL 中。 - MGorgon
你是在谈论viewparams吗?https://dev59.com/Nmw15IYBdhLWcg3w0fEV - Jaqen H'ghar
@Jaqen H´ghar 看起来你找到了我想要的东西。我不知道JSF支持这样的参数。我需要进一步“清理”f:viewparams还是可以信任它们? - ForguesR
我认为,除非它们被绑定到字符串,否则它们已经通过转换器处理过,因此是完全安全的。而且你还可以选择使用验证器。如果绑定到字符串,你应该考虑它将用于什么。你甚至可以直接将其绑定到bean.clientM并使用转换器 - 这个转换器应该将字符串转换为整数并查找实体,所以如果参数无效,它将抛出NumberFormatException。 - Jaqen H'ghar
3个回答

2

我认为以下这些做法是最佳实践:

displayclient.xhtml:

<f:metadata>
    <f:viewParam name=“entityId” 
                 value="#{bean.clientM}” 
                 required="true" 
                 converter=“clientModelConverter”
                 converterMessage="Bad request. Unknown ClientModel.”
                 requiredMessage="Bad request. Please use a link from within the system.">
    </f:viewParam>
</f:metadata>

转换器:

@ManagedBean    
@RequestScoped 
public class ClientModelConverter implements Converter {

    @EJB
    private ClientService clientService;

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        // TODO: check if value is instanceof ClientModel
        return String.valueOf(((ClientModel) value).getId());
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
       // TODO: catch NumberFormatException and throw ConverterException
       return clientService.find(Integer.valueOf(value));
    }

}

使用以下方式调用页面:

<h:link value=“Display” outcome="displayClient">
    <f:param name=“entityId" value=“#{…}” />
</h:link>

或者只是一个原始的URL,例如displayClient.xhtml?entityId=123

受到<f:metadata>、<f:viewParam>和<f:viewAction>可以用于什么?JSF 2.0视图参数传递对象的启发。


0

我做了类似的事情,出于完全相同的原因:提供到 jsf 页面的外部链接。

在你的 ViewScoped bean 中,有一个 @PostConstruct 方法来强制进行 Get Param 的故障扫描

@PostConstruct
public void scanEntityId(){

    int entityId = 0; // or some other default value 

    try{
        // Try to fetch entityId from url with GET
        int entityId = Integer.getInteger(FacesContext.getExternalContext().getRequestParameterMap().get("entityId")  );
    }catch(Exception e){
        // Did not find anything from GET
    }

    // TODO: do stuff using the entityId's value. e.g.:
    if(entityId >0){
        this.clientM = this.clientS.find(entityId);
    }
}

请确保处理在Get参数中未找到entityId变量的情况

如果您想从同一应用程序的另一个xhtml页面链接到该页面,可以使用f:param

<h:link value="Go in a page that uses thatViewScoped Bean"
    outcome="#{thatViewScopedBean.takeMeToThatPage}" >      
    <f:param name="entityId" value="#{somebean.somevar.entityId}" />
</h:link>

这里还有一个不错的教程在这里可以找到。 你可能也想看看这个答案,以及这篇文章来获取更多选项并获得更清晰的视角。


@JaqenH'ghar,你也提出了一个带有f:param的h:link。我不确定你的意思是什么。 - yannicuLar
1
但是你没有使用ViewParam,对我来说这似乎是标准路线。是的,结果或多或少相同,只是你在postconstruct中有代码,而我在转换器中有它。无论如何,一切都可能有效,我们只是有太多选择 :-) - Jaqen H'ghar
1
我正在使用链接/link和f:param来链接页面,就像你所做的那样。这与“读取”identityId参数无关。带有转换器的viewParam(看起来很整洁,我没有想到:))用于读取值,而f:param用于设置它。 - yannicuLar
我是另一种理解这个问题的方式,即它主要是关于读取参数。 - Jaqen H'ghar
哦,我以为你在比较f:param和f:viewParam。我的错,对不起!嗯,我想转换器的想法是一种更精细的读取值的方式,毕竟@BallusC提出了它!!我会点赞你的答案。 - yannicuLar
显示剩余3条评论

0
  1. 将entityId存储在会话中,例如SessionScoped Bean
  2. 在您的View Scoped托管bean中,添加@PostConstruct方法,在此方法中从会话中获取entityId并使用它填充数据

这正是我现在拥有的。我想使用URL获取参数的原因是因为我的Web应用程序将与另一个应用程序“链接”起来。 - ForguesR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接