[英]Post request on sling servlet not working on publish instance
昨天,我在用資源類型屬性注冊的AEM 6.3中編寫sling post servlet時遇到問題。 實際上,我的代碼適用於作者實例,但不適用於發布實例。 下面的代碼使用用戶給定的數據在項目的內容路徑上創建節點和屬性。 (忽略以下代碼中的導入語句和分號,它是用groovy編寫的)
我不確定,通過使用SlingHttpServletRequest實例並獲取會話來解析資源是否是一種好習慣?
而且,我能夠找到session.save()或resolver.commit之間的任何區別。
誰能幫忙嗎?
@SlingServlet(
resourceTypes = ["app/project/components/formComp"],
extensions = ['json'],
methods = "POST")
@Properties([
@Property(name = "Code ABC", value = 'Project ABC'),
@Property(name = "Description ABC", value = 'servlet form')])
@CompileStatic
@Slf4j
class PostFormServlet extends SlingAllMethodsServlet {
ResourceResolver resolver
Session session
@Override
void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) {
String myNodePath = 'content/project/en/mynode'
String requestParam = 'param'
try {
resolver = request.getResourceResolver()
session = resolver.adaptTo(Session)
Node root = session.getRootNode()
Node myDestinationNode
if (rootNode.hasNode(myNodePath)) {
myDestinationNode = rootNode.getNode(myNodePath)
} else {
myDestinationNode = rootNode.addNode(myNodePath, NT_UNSTRUCTURED)
}
String paramValue = request.getParameter(requestParam)
if (myDestinationNode) {
Date date = new Date();
timeStamp = date.getTime() as String
Node dateTimeNode = myDestinationNode.addNode(timeStamp, NT_UNSTRUCTURED)
if (dateTimeNode) {
dateTimeNode.setProperty(requestParam, paramValue)
}
}
session.save()
} catch (Exception ex) {
//log error
}
response.contentType = 'application/json'
response.getWriter().write("Node Created")
}
}
如果以管理員用戶身份發出POST請求,則您的Servlet可以正常工作。 因此,腳本解析工作正常,這是權限問題。
在幾層檢查權限:
權限檢查-調度程序:調度程序可能不允許某些路徑的POST請求,或者需要某種身份驗證,或者只是從請求中刪除一些查詢參數或其他有效負載。 但是,如果錯誤消息是來自Apache還是來自發布服務器,則很容易識別。 否則,您可以通過分派器發送一次POST請求,然后直接發送到發布者一次。 如果結果不同,那么您必須首先照顧Dispatcher。
權限檢查-Apache Sling身份驗證服務:這主要與作者有關,因為默認情況下發布者是相當開放的。 該服務簡單地說,可以匿名訪問哪些路徑(意味着無需任何身份驗證),以及將用戶轉發到登錄頁面的路徑。 可以通過OSGi或通過直接在Servlet中指定sling.auth.requirements
屬性來配置此服務。 身份驗證服務將讀取此類屬性,並將其視為自身的配置。 如前所述,它主要與作者有關-默認情況下,只有登錄頁面無需身份驗證即可訪問。
權限檢查-內容資源:如果您通過SlingResourceType注冊Servlet,則腳本解析過程需要對所請求資源的讀取權限。 在發布服務器上, /content/...
-tree通常對於匿名用戶是可讀的,但不像/app/...
。 如果在路徑上注冊Servlet,則可以輕松避免這種情況。 對於此類servlet,沒有Sling權限檢查(好壞取決於所需要的內容)。
Servlet的權限
上面的權限檢查是相關的,即調用了Servlet。 但是,如果被調用,則Servlet仍然僅具有調用用戶的讀取和寫入權限。 這是非常少的匿名用戶( 讀取/ content / ...,沒有寫權限 )。
因此,您需要與服務用戶打開一個新會話。
public class TestServlet extends SlingAllMethodsServlet {
@Reference
private ResourceResolverFactory resolverFactory;
@Override
protected void doPost(@Nonnull SlingHttpServletRequest request, @Nonnull SlingHttpServletResponse response) throws ServletException, IOException {
final Map<String, Object> authenticationInfo = Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "testservlet");
try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(authenticationInfo)) {
Resource rootRes = resolver.getResource("/content/....");
resolver.create(rootRes, "test", null);
resolver.commit();
} catch (Exception e) {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
e.printStackTrace(response.getWriter());
}
}
}
一開始,它會說類似org.apache.sling.api.resource.LoginException: Cannot derive user name for bundle ...
。
你需要:
請遵循以下說明:
https://helpx.adobe.com/experience-manager/6-3/sites/administering/using/security-service-users.html
或使用工具創建服務用戶並為其授予權限。 或者您已經使用過一個,或者我建議使用https://github.com/Netcentric/accesscontroltool 。 映射仍然需要OSGi配置。
如果服務用戶對於第一次試用而言過於復雜,則仍可以使用不推薦使用的ResourceResolver resolver = resolverFactory.getAdministrativeResourceResolver(null)
。 它不安全,因此已棄用。 您只需要通過OSGi配置將捆綁軟件列入白名單(Apache Sling登錄管理員白名單-其他捆綁軟件)
最后一個問題:
session.save()或resolver.commit之間的區別
解析程序是圍繞Jackrabbit-Oak會話的Sling-wrapper。 所以resolver.commit()是自動調用session.save()的(但不是這樣)。
強烈建議使用您可以使用的最高級別的API-請勿將高級和低級API混合使用。 可能會發生例外-但對於初學者而言不會。 (例如,PageManager-API是建立在Slings Resource-API之上的,而Slings Resource-API是建立在Jackrabbit OAK的Node-API之上的。困難是要知道哪個API存在)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.