【问题标题】:How to safely init a ViewScoped bean with URL GET request parameters? [duplicate]如何使用 URL GET 请求参数安全地初始化 ViewScoped bean? [复制]
【发布时间】:2014-09-04 20:27:50
【问题描述】:

我有一些托管 bean (ViewScoped),当前使用会话中的数据进行了初始化。我想用 URL GET 参数初始化它们,这样我就可以为 URL 提供我想在视图中显示的实体 ID。类似于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 中
  • 你在谈论视图参数吗? stackoverflow.com/questions/6377798/…
  • @Jaqen H´ghar 看起来你完全找到了我想要的东西。我不知道 JSF 支持这样的参数。我需要进一步清理 f:viewparams 还是可以通过这种方式信任它?
  • 我会说除非它们被绑定到一个字符串,否则它们已经通过了转换器,因此是完全安全的。您还可以选择使用验证器。如果绑定到字符串,您可能应该考虑它的确切用途。您甚至可以将其直接绑定到 bean.clientM 并使用转换器 - 然后此转换器应将 String 转换为 Integer 并 find() 实体,因此如果参数无效,它将抛出 NumberFormatException

标签: jsf jsf-2


【解决方案1】:

我认为最好的做法是:

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>

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

深受启发 What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?JSF 2.0 view parameters to pass objects.

【讨论】:

    【解决方案2】:

    出于同样的确切原因,我做了类似的事情:提供指向 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);
        }
    }
    

    只需确保处理在获取参数中找不到 entityId var 的情况

    如果您想从同一应用的另一个 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>
    

    一个不错的教程也可以找到here 您可能还想see this answer 和此article 以查看更多选项并获得更清晰的视图。

    【讨论】:

    • 这是否有原因而不是 f:viewparam?
    • @JaqenH'ghar 你也提出了一个带有 f:param 的 h:link。我不确定我明白你的意思。
    • 但是您没有使用 ViewParam,对我来说这看起来是标准路线。是的,结果或多或少是一样的,只有你在 postconstruct 中有代码,而我在转换器中有它。无论如何,一切都可能有效,我们只是有太多选择:-)
    • 我使用 link/f:param 链接到页面,就像你做的那样。它与“读取”identityId 参数无关。带有转换器的 viewParam(顺便说一句,看起来很整洁,我没想到 :))用于 read 值,而 f:param 用于 set 它.
    【解决方案3】:
    1. 在会话中存储 entityId,例如 SessionScoped Bean
    2. 在您的 View Scoped 托管 bean 中,添加 @PostConstruct 方法,您将从会话中获取 entityId 并使用它填充数据

    【讨论】:

    • 这正是我现在所拥有的。为什么我要使用 URL 获取参数是因为我的 Web 应用程序将与其他应用程序链接
    猜你喜欢
    • 2011-12-05
    • 2013-11-20
    • 2014-06-21
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    相关资源
    最近更新 更多