在AEM中取得管理工作階段或資源解析程式的主要方式是使用Sling提供的SlingRepository.loginAdministrative()
和ResourceResolverFactory.getAdministrativeResourceResolver()
方法。
但是,這兩種方法都沒有圍繞最少權限原則設計,而且讓開發人員過於容易,無法為其內容早期規劃適當的結構和相應的訪問控制級別(ACL)。 如果此類服務中存在漏洞,則通常會導致向admin
用戶提供權限升級,即使代碼本身不需要管理權限也能正常工作。
有時可能未使用管理工作階段,或完全停用功能。 如果您的實作就是這樣,請確定您完全移除功能,或將它與NOP程式碼搭配使用。
在可能的情況下重新調整您的功能,讓指定的已驗證要求工作階段可用來讀取或寫入內容。 如果這不可行,則通常可以採用下列優先事項。
許多問題都可以透過重組內容來解決。 進行重組時,請牢記以下簡單規則:
更改訪問控制
調整內容結構
將程式碼重新調整為適當的服務
此外,請確定您開發的任何新功能都遵循下列原則:
安全性需求應推動內容結構
使用節點類型
尊重隱私權設定
/profile
節點上找到的配置檔案圖片、電子郵件或全名。無論您是在重組內容時應用訪問控制還是為新服務用戶應用訪問控制,都必須盡可能應用最嚴格的ACL。 使用所有可能的訪問控制設施:
例如,不應在/apps
上套用jcr:read
,而只將它套用至/apps/*/components/*/analytics
為節點類型應用ACL
限制權限
jcr:write
權限;請改用jcr:modifyProperties
如果上述失敗,Sling 7提供Service User Mapping服務,可設定Bundle-to-user對應和兩種對應的API方法: [SlingRepository.loginService()](https://sling.apache.org/apidocs/sling7/org/apache/sling/jcr/api/SlingRepository.html#loginService-java.lang.String-java.lang.String-)
和 [ResourceResolverFactory.getServiceResourceResolver()](https://sling.apache.org/apidocs/sling7/org/apache/sling/api/resource/ResourceResolverFactory.html#getServiceResourceResolver-java.util.Map-)
,它們僅返回具有已配置用戶權限的會話/資源解析器。 這些方法具有以下特點:
它們允許將服務對應給用戶
他們使子服務用戶定義更容易
中心配置點是:org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl
service-id
= service-name
[ ":"子服務名稱 ]
service-id
映射到資源解析器和/或JCR儲存庫用戶ID以進行驗證
service-name
是提供服務的包的符號名稱
服務用戶是JCR用戶,沒有設定口令和執行特定任務所需的最少權限集。 沒有設定密碼表示無法與服務使用者登入。
取代管理作業的方法,是以服務使用者作業取代。 如有需要,也可以由多個子服務使用者取代。
若要以服務使用者取代管理工作階段,您應執行下列步驟:
確定您服務的必要權限,並牢記最低權限的原則。
檢查是否已有使用者具備您所需的權限設定。 如果沒有符合您需求的現有使用者,請建立新的系統服務使用者。 需要RTC才能建立新的服務用戶。 有時,建立多個子服務用戶(例如,一個用於寫作,一個用於閱讀)來劃分更多訪問是明智的。
為您的用戶設定和測試ACE。
為服務和user/sub-users
添加service-user
映射
將服務使用者sling功能提供給您的搭售:更新至org.apache.sling.api
的最新版本。
將程式碼中的admin-session
取代為loginService
或getServiceResourceResolver
API。
在您確認AEM服務使用者清單中的使用者不適用於您的使用案例,且相應的RTC問題已獲得核准後,您就可以將新使用者新增至預設內容。
建議的方法是建立服務用戶,以使用位於https://<server>:<port>/crx/explorer/index.jsp的儲存庫瀏覽器
其目標是取得有效的jcr:uuid
屬性,這是透過內容封裝安裝來建立使用者的必要屬性。
您可以通過以下方式建立服務用戶:
前往位於https://<server>:<port>/crx/explorer/index.jsp的儲存庫瀏覽器
按螢幕左上角的登錄連結以管理員身份登錄。
接著,建立並命名您的系統使用者。 要將用戶建立為系統用戶,請將中間路徑設定為system
,並根據您的需要添加可選子資料夾:
驗證您的系統用戶節點的外觀如下:
請注意,沒有與服務使用者相關聯的混音類型。 這表示系統使用者將沒有存取控制原則。
將對應的。content.xml新增至套件內容時,請確定您已設定rep:authorizableId
,且主要類型為rep:SystemUser
。 應該是這樣的:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="https://www.jcp.org/jcr/1.0" xmlns:rep="internal"
jcr:primaryType="rep:SystemUser"
jcr:uuid="4917dd68-a0c1-3021-b5b7-435d0044b0dd"
rep:principalName="authentication-service"
rep:authorizableId="authentication-service"/>
要從服務向相應的系統用戶添加映射,您需要為 [ServiceUserMapper](https://sling.apache.org/apidocs/sling7/org/apache/sling/serviceusermapping/ServiceUserMapper.html)
服務建立工廠配置。 為了保持這種模組,可使用Sling amend mechanism提供這種配置。 建議使用Sling Initial Content Loading來安裝搭售的這類組態:
在您搭售的src/main/resources資料夾下建立子資料夾SLING-INF/content
在此資料夾中,建立名為org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.refined-<您工廠組態的某個唯一名稱>.xml,並包含您工廠組態的內容(包括所有子服務使用者映射)。 範例:
在您套裝的src/main/resources
資料夾下方建立SLING-INF/content
資料夾;
在此資料夾中建立一個檔案named org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-<a unique name for your factory configuration>.xml
,其中包含出廠配置的內容,包括所有子服務用戶映射。
為了便於說明,請使用名為org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-com.adobe.granite.auth.saml.xml
的檔案:
<?xml version="1.0" encoding="UTF-8"?>
<node>
<primaryNodeType>sling:OsgiConfig</primaryNodeType>
<property>
<name>user.default</name>
<value></value>
</property>
<property>
<name>user.mapping</name>
<values>
<value>com.adobe.granite.auth.saml=authentication-service</value>
</values>
</property>
</node>
在您搭售的pom.xml
中的maven-bundle-plugin
組態中參考Sling初始內容。 範例:
<Sling-Initial-Content>
SLING-INF/content;path:=/libs/system/config;overwrite:=true;
</Sling-Initial-Content>
安裝您的套件,並確定已安裝工廠配置。 您可以透過下列方式執行此動作:
對loginAdministrative()
的呼叫通常會與共用作業一起顯示。 這些會話是在服務啟動時獲得的,並且僅在服務停止後才註銷。 雖然這是常見的做法,但它導致了兩個問題:
最顯而易見的安全風險解決方案是,只需將loginAdministrative()
呼叫替換為loginService()
呼叫,以限制權限讓使用者接受。 但是,這不會對任何潛在的效能降級產生任何影響。 可能的緩解措施是,將所有請求的資訊包在與會話無關聯的對象中。 然後,視需要建立(或銷毀)工作階段。
建議的方法是重新調整服務的API,讓呼叫者控制建立/銷毀工作階段。
JSP無法使用loginService()
,因為沒有相關服務。 不過,JSP中的管理會話通常是違反MVC模式的信號。
這可以用兩種方式來修正:
第一種方法是優選的方法。
處理事件或工作時(在某些情況下),觸發事件的對應作業通常會遺失。 這會導致事件處理常常使用管理作業來處理其工作。 要解決這個問題,可以想見的方法各不相同,各有其優點和缺點:
在事件裝載中傳遞user-id
並使用模擬。
優點: 易於使用。
缺點: 仍使用 loginAdministrative()
。它會重新驗證已經驗證的請求。
建立或重複使用可存取資料的服務使用者。
優點: 符合目前的設計。需要最少的變更。
缺點:需 要非常強大的服務用戶才能靈活,這很容易導致權限升級。避開安全模型。
在事件裝載中傳遞Subject
的序列化,並根據該主題建立ResourceResolver
。 例如,在ResourceResolverFactory
中使用JAAS doAsPrivileged
。
優點:從 安全性的角度進行簡潔的實作。它避免了重認證,並且以原始權限操作。 安全相關程式碼對事件的使用者是透明的。
缺點:需 要重構。安全相關程式碼對事件的使用者透明,這個事實也可能導致問題。
第三種方法目前是首選的處理技術。
在工作流進程實現中,觸發工作流的相應用戶會話通常丟失。 這會導致工作流程程式通常使用管理工作階段來執行其工作。
為瞭解決這些問題,建議使用處理事件、複製預處理器和作業中提及的相同方法。
在sling POST處理器實作中使用數個管理工作階段。 通常,管理會話用於訪問正在處理的POST中待刪除的節點。 因此,它們不再透過請求作業階段提供。 可以訪問一個節點待刪除,以揭露其他情況下不可訪問的元資料。