首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JSF <protected-views>令牌不一致

JSF <protected-views>令牌不一致
EN

Stack Overflow用户
提问于 2017-05-23 11:09:34
回答 1查看 871关注 0票数 0

关于JSF的<protected-views>生成的令牌,我目前遇到了问题。

我添加了要在faces-config.xml中保护的页面

代码语言:javascript
复制
<protected-views>
    <url-pattern>/restricted/account-management/users.xhtml</url-pattern>
    <url-pattern>/restricted/account-management/users.jsf</url-pattern>
</protected-views>

然后,例如,当我使用<h:link>转到用户页面时

代码语言:javascript
复制
<h:link outcome="users" title="View">
    <f:param name="user" value="#{e.id}" />
</h:link>

URL中生成的标记如下所示

代码语言:javascript
复制
/restricted/account-management/users.jsf?javax.faces.Token=OW5KkkfJZrrfmZSXwA%253D%253D&user=4

该页面返回一个ProtectedViewException

然后我发现正确的令牌实际上是:

代码语言:javascript
复制
/restricted/account-management/users.jsf?javax.faces.Token=OW5KkkfJZrrfmZSXwA%3D%3D

令牌被编码在URL中,其中%变成了%25。当我将正确的令牌复制粘贴到URL中时,我成功地进入了users页面。

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2017-11-06 23:03:11

这是Mojarra JSF实现的2.2.11和更高版本的问题,您可以在https://github.com/javaee/javaserverfaces-spec/issues/1161和这里https://github.com/javaserverfaces/mojarra/issues/4139中查看有关该问题的详细信息

处理该问题的替代方案之一是创建一个CustomExternalContext来处理双重编码。

首先,您需要在faces-config.xml中声明一个CustomExternalContextFactory:

代码语言:javascript
复制
<factory>
    <external-context-factory>com.proitc.config.CustomExternalContextFactory</external-context-factory>
</factory>

在ExternalContextFactory中定义CustomExternalContext:

代码语言:javascript
复制
public class CustomExternalContextFactory extends ExternalContextFactory {

  private ExternalContextFactory externalContextFactory;

  public CustomExternalContextFactory() {}

  public CustomExternalContextFactory(ExternalContextFactory externalContextFactory) {
    this.externalContextFactory = externalContextFactory;
  }

  @Override
  public ExternalContext getExternalContext(Object context, Object request, Object response)
      throws FacesException {

    ExternalContext handler = new CustomExternalContext((ServletContext) context,
        (HttpServletRequest) request, (HttpServletResponse) response);

    return handler;
  }

}

CustomExternalContext覆盖encodeBookmarkableURL和encodeRedirectURL方法:

代码语言:javascript
复制
public class CustomExternalContext extends ExternalContextImpl {

  public CustomExternalContext(ServletContext sc, ServletRequest request,
      ServletResponse response) {
    super(sc, request, response);
  }

  @Override
  public String encodeBookmarkableURL(String baseUrl, Map<String, List<String>> parameters) {
    FacesContext context = FacesContext.getCurrentInstance();
    String encodingFromContext =
        (String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
    if (null == encodingFromContext) {
      encodingFromContext =
          (String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
    }
    String currentResponseEncoding =
        (null != encodingFromContext) ? encodingFromContext : getResponseCharacterEncoding();
    UrlBuilder builder = new UrlBuilder(baseUrl, currentResponseEncoding);
    builder.addParameters(parameters);
    String secureUrl = builder.createUrl();

    //Handle double encoding
    if (parameters.size() > 0 && baseUrl.contains("javax.faces.Token")) {
      try {
        int beginToken = secureUrl.indexOf("javax.faces.Token");
        int endToken = secureUrl.indexOf("&") - 1;
        String doubleEncodeToken = secureUrl.substring(beginToken, endToken);
        String encodeToken = URLDecoder.decode(doubleEncodeToken, currentResponseEncoding);
        secureUrl = secureUrl.replace(doubleEncodeToken, encodeToken);
      } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
      }
    }
    return secureUrl;
  }

  @Override
  public String encodeRedirectURL(String baseUrl, Map<String, List<String>> parameters) {
    FacesContext context = FacesContext.getCurrentInstance();
    String encodingFromContext =
        (String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
    if (null == encodingFromContext) {
      encodingFromContext =
          (String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
    }

    String currentResponseEncoding =
        (null != encodingFromContext) ? encodingFromContext : getResponseCharacterEncoding();

    UrlBuilder builder = new UrlBuilder(baseUrl, currentResponseEncoding);
    builder.addParameters(parameters);
    String secureUrl = builder.createUrl();
    //Handle double encoding
    if (parameters.size() > 0 && baseUrl.contains("javax.faces.Token")) {
      try {
        int beginToken = secureUrl.indexOf("javax.faces.Token");
        int endToken = secureUrl.indexOf("&") - 1;
        String doubleEncodeToken = secureUrl.substring(beginToken, endToken);
        String encodeToken = URLDecoder.decode(doubleEncodeToken, currentResponseEncoding);
        secureUrl = secureUrl.replace(doubleEncodeToken, encodeToken);
      } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
      }
    }
    return secureUrl;
  }

}

您可以在https://github.com/earth001/jsf-protected-view中找到一个可用的示例

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44125142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档