Java 用于包装请求正文的吊索过滤器
用例: 我们正在开发一个AEM封闭用户组网站,用户需要提交触发工作流的表单。由于用户经过身份验证,部分工作流负载需要包括发起表单的用户 我正在考虑为此使用AEM表单,它保存到Java 用于包装请求正文的吊索过滤器,java,servlets,aem,sling,Java,Servlets,Aem,Sling,用例: 我们正在开发一个AEM封闭用户组网站,用户需要提交触发工作流的表单。由于用户经过身份验证,部分工作流负载需要包括发起表单的用户 我正在考虑为此使用AEM表单,它保存到/content/usergenerated/content/Forms/af/my site下的节点,但有效负载中没有提到用户(仅服务用户)。在这种情况下,有两个服务用户:运行工作流的工作流服务和处理表单处理和初始保存的fd服务。例如,从工作流步骤调用的以下代码报告“fd服务” workItem.getWorkflowDa
/content/usergenerated/content/Forms/af/my site
下的节点,但有效负载中没有提到用户(仅服务用户)。在这种情况下,有两个服务用户:运行工作流的工作流服务和处理表单处理和初始保存的fd服务。例如,从工作流步骤调用的以下代码报告“fd服务”
workItem.getWorkflowData().getMetaDataMap().get("userId", String.class);
为了克服这一限制
从发布AEM实例启动的工作流:当从AEM发布实例提交自适应表单、交互式通信或信函时,使用服务用户创建所有工作流实例。在这些情况下,工作流实例数据中不会捕获登录用户的用户名
在AEM表单servlet使用请求包装器修改请求主体并添加原始用户ID之前,我添加了一个过滤器servlet来截获初始表单提交
在表单、工作流和启动器方面。。这就是我的基本设置
我审查了以下资源:
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletInputStream;
import java.io.*;
public class FormSubmitRequestWrapper extends SlingHttpServletRequestWrapper {
String requestPayload;
private static final Logger log = LoggerFactory.getLogger(FormSubmitRequestWrapper.class);
public FormSubmitRequestWrapper(SlingHttpServletRequest slingRequest) {
super(slingRequest);
// read the original payload into the requestPayload variable
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
// read the payload into the StringBuilder
InputStream inputStream = slingRequest.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
// make an empty string since there is no payload
stringBuilder.append("");
}
} catch (IOException ex) {
log.error("Error reading the request payload", ex);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException iox) {
log.error("Error closing bufferedReader", iox);
}
}
}
requestPayload = stringBuilder.toString();
}
/**
* Override of the getInputStream() method which returns an InputStream that reads from the
* stored requestPayload string instead of from the request's actual InputStream.
*/
@Override
public ServletInputStream getInputStream ()
throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestPayload.getBytes());
ServletInputStream inputStream = new ServletInputStream() {
public int read ()
throws IOException {
return byteArrayInputStream.read();
}
};
return inputStream;
}
}
这是我的过滤器
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.engine.EngineConstants;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Session;
import javax.servlet.*;
import java.io.IOException;
@Component(service = Filter.class,
immediate = true,
property = {
Constants.SERVICE_DESCRIPTION + "=Add the CUG userID to any UGC posts",
EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,
Constants.SERVICE_RANKING + ":Integer=3000",
EngineConstants.SLING_FILTER_PATTERN + "=/content/forms/af/my-site.*"
})
public class DecorateUserGeneratedFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(DecorateUserGeneratedFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final SlingHttpServletResponse slingResponse = (SlingHttpServletResponse ) response;
final SlingHttpServletRequest slingRequest= (SlingHttpServletRequest) request;
FormSubmitRequestWrapper wrappedRequest = new FormSubmitRequestWrapper(slingRequest);
log.info("starting ConfirmAlumniStatus workflow");
log.info(getCurrentUserId(slingRequest));
chain.doFilter(wrappedRequest, slingResponse);
}
@Override
public void destroy() {
}
public String getCurrentUserId(SlingHttpServletRequest request) {
ResourceResolver resolver = request.getResourceResolver();
Session session = resolver.adaptTo(Session.class);
String userId = session.getUserID();
return userId;
}
}
当提交的帖子被这个过滤器处理时,我会得到下面的错误,说明请求主体已经被读取。因此,似乎过滤器排名可能不够高
2018年6月25日13:11:13.200错误[0:0:0:0:0:0:0:0:1[1529946669719]POST/content/forms/af/my site/request access/jcr:content/guideContainer.af.internalsubmit.jsp
HTTP/1.1]org.apache.sling.engine.impl.SlingRequestProcessorImpl
服务:未捕获的可丢弃java.lang.IllegalStateException:请求
数据已在上读取
org.apache.sling.engine.impl.request.RequestData.getInputStream(RequestData.java:669)
在
org.apache.sling.engine.impl.SlingHttpServletRequestImpl.getInputStream(SlingHttpServletRequestImpl.java:292)
在
servlet.ServletRequestWrapper.getInputStream(ServletRequestWrapper.java:136)
在
my.site.servlets.FormSubmitRequestWrapper.(FormSubmitRequestWrapper.java:26)
在
my.site.servlets.DecorateUserGeneratedFilter.doFilter(DecorateUserGeneratedFilter.java:75)
在
org.apache.sling.engine.impl.filter.AbstractSlingFilterChain.doFilter(AbstractSlingFilterChain.java:68)
在
org.apache.sling.engine.impl.filter.AbstractSlingFilterChain.doFilter(AbstractSlingFilterChain.java:73)
在
org.apache.sling.engine.impl.filter.AbstractSlingFilterChain.doFilter(AbstractSlingFilterChain.java:73)
在
com.cognifide.cq.includefilter.DynamicIncludeFilter.doFilter(DynamicIncludeFilter.java:82)
在
org.apache.sling.engine.impl.filter.AbstractSlingFilterChain.doFilter(AbstractSlingFilterChain.java:68)
在
org.apache.sling.engine.impl.debug.RequestProgressTrackerLogFilter.doFilter(RequestProgressTrackerLogFilter.java:10
我认为服务排名不起作用。当我查看
我的过滤器如图所示列出。从列出的其他过滤器来看,我认为最左边的数字是过滤器排名。出于某种原因,我的过滤器排名为0,即使我将其设置为服务。排名=700
0:类my.site.servlets.DecorateUserGeneratedFilter(id:
8402,属性:service.ranking=700);调用:0;时间:0ms;时间/调用:
-1µs
更新:我能够修复筛选器列组,使其700仍然给出IllegalStateException。使其3000使该问题消失。但是当从我的包装器调用request.getInputStream()时,它返回null。正确的想法,错误的位置 简单的回答是,当您实现SlingHttpServletRequestWrapper时,如果您正在动态添加参数,它将提供对原始SlingHttpServletRequest的方法调用的默认处理。您要做的是确保覆盖与参数交互的方法,以便您可以确保因此,在初始化时,调用原始参数映射,将这些项复制到包含您自己的值的新映射中 然后超越任何请求这些值的方法
getParameter(String)
getParameterMap()
getParameterNames()
getParameterValues(String)
不要触摸InputStream,它已被处理以获取传入的任何参数
此外,这是处理此类用例的两种方法之一,另一种方法是使用所记录的SlingPostProcessor
它允许您检测正在写入存储库的内容,并修改数据,使其像您的案例一样包含一个附加字段。正确的想法,错误的位置 简单的回答是,当您实现SlingHttpServletRequestWrapper时,如果您正在动态添加参数,它将提供对原始SlingHttpServletRequest的方法调用的默认处理。您要做的是确保覆盖与参数交互的方法,以便您可以确保因此,在初始化时,调用原始参数映射,将这些项复制到包含您自己的值的新映射中 然后超越任何请求这些值的方法
getParameter(String)
getParameterMap()
getParameterNames()
getParameterValues(String)
不要触摸InputStream,它已被处理以获取传入的任何参数
此外,这是处理此类用例的两种方法之一,另一种方法是使用所记录的SlingPostProcessor
它允许您检测正在写入存储库的内容,并修改数据,使其像您的案例一样包含一个附加字段。您尝试执行的操作可能很简单,但对于新的AEM版本来说可能不是未来的证明 您需要完全控制工作流的触发方式!: