关于JSF的<protected-views>生成的令牌,我目前遇到了问题。
我添加了要在faces-config.xml中保护的页面
<protected-views>
<url-pattern>/restricted/account-management/users.xhtml</url-pattern>
<url-pattern>/restricted/account-management/users.jsf</url-pattern>
</protected-views>然后,例如,当我使用<h:link>转到用户页面时
<h:link outcome="users" title="View">
<f:param name="user" value="#{e.id}" />
</h:link>URL中生成的标记如下所示
/restricted/account-management/users.jsf?javax.faces.Token=OW5KkkfJZrrfmZSXwA%253D%253D&user=4该页面返回一个ProtectedViewException
然后我发现正确的令牌实际上是:
/restricted/account-management/users.jsf?javax.faces.Token=OW5KkkfJZrrfmZSXwA%3D%3D令牌被编码在URL中,其中%变成了%25。当我将正确的令牌复制粘贴到URL中时,我成功地进入了users页面。
任何帮助都将不胜感激。
发布于 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:
<factory>
<external-context-factory>com.proitc.config.CustomExternalContextFactory</external-context-factory>
</factory>在ExternalContextFactory中定义CustomExternalContext:
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方法:
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中找到一个可用的示例
https://stackoverflow.com/questions/44125142
复制相似问题