이 콘텐츠는 선택한 언어로 제공되지 않습니다.

Chapter 15. Extending the Hierarchical Database


You can create customized extensions to the hierarchical database. To do so you will need to write Java code, and to use Maven 3 for the build system.

15.1. Custom Authentication and Authorization Modules

15.1.1. The AuthenticationProvider Interface

The hierarchical database defines a simple interface for authenticating users. Each repository can have multiple authentication modules, and a client is authenticated as soon as one of the modules accepts the credentials. The interface is quite simple:
/**
 * An interface used by a ModeShape Repository for authenticating users when they create new sessions
 * using Repository.login(javax.jcr.Credentials, String)} and related methods.
 */
public interface AuthenticationProvider {

    /**
     * Authenticate the user that is using the supplied credentials. If the supplied credentials are authenticated, this
     * method should construct an ExecutionContext that reflects the authenticated environment, including the context's
     * valid SecurityContext security context that will be used for authorization throughout.
     *
     * Note that each provider is handed a map into which it can place name-value pairs that will be used in the
     * Session attributes of the Session that results from this authentication attempt.
     * ModeShape will ignore any attributes if this provider does not authenticate the credentials.
     *
     *
     * @param credentials the user's JCR credentials, which may be an AnonymousCredentials if authenticating as an
     *        anonymous user
     * @param repositoryName the name of the JCR repository; never null
     * @param workspaceName the name of the JCR workspace; never null
     * @param repositoryContext the execution context of the repository, which may be wrapped by this method
     * @param sessionAttributes the map of name-value pairs that will be placed into the Session attributes; never null
     * @return the execution context for the authenticated user, or null if this provider could not authenticate the user
     */
    ExecutionContext authenticate( Credentials credentials,
                                   String repositoryName,
                                   String workspaceName,
                                   ExecutionContext repositoryContext,
                                   Map<String, Object> sessionAttributes );

}
Copy to Clipboard Toggle word wrap
All the parameters are supplied by the hierarchical database and contain everything necessary to authenticate a client attempting to create a new JCR Session.
Implementations are expected to return a new ExecutionContext instance for the user, and this can be created from the repository's execution context by calling repositoryContext.with(securityContext) , where securityContext is a custom implementation of the org.modeshape.jcr.security.SecurityContext interface that returns information about the authenticated user:
/**
 * A security context provides a pluggable means to support disparate authentication and authorization mechanisms that specify the
 * user name and roles.
 *
 * A security context should only be associated with the execution context after authentication has occurred.
 */
@NotThreadSafe
public interface SecurityContext {

    /**
     * Return whether this security context is an anonymous context.
     * @return true if this context represents an anonymous user, or false otherwise
     */
    boolean isAnonymous();

    /**
     * Returns the authenticated user's name
     * @return the authenticated user's name
     */
    String getUserName();

    /**
     * Returns whether the authenticated user has the given role.
     * @param roleName the name of the role to check
     * @return true if the user has the role and is logged in; false otherwise
     */
    boolean hasRole( String roleName );

    /**
     * Logs the user out of the authentication mechanism.
     * For some authentication mechanisms, this will be implemented as a no-op.
     */
    void logout();
}
Copy to Clipboard Toggle word wrap
Note that if you want to provide authorization functionality, then your SecurityContext implementation must also implement AuthorizationProvider or AdvancedAuthorizationProvider .

15.1.2. The AuthorizationProvider Interface

The hierarchical database uses its org.modeshape.jcr.security.AuthorizationProvider interface to determine whether a Session has the appropriate privileges to perform reads and writes.
/**
 * An interface that can authorize access to specific resources within repositories.
 */
public interface AuthorizationProvider {

    /**
     * Determine if the supplied execution context has permission for all of the named actions in the named workspace.
     * If not all actions are allowed, the method returns false.
     *
     * @param context the context in which the subject is performing the actions on the supplied workspace
     * @param repositoryName the name of the repository containing the workspace content
     * @param repositorySourceName <i>This is no longer used and will always be the same as the repositoryName</i>
     * @param workspaceName the name of the workspace in which the path exists
     * @param path the path on which the actions are occurring
     * @param actions the list of {@link ModeShapePermissions actions} to check
     * @return true if the subject has privilege to perform all of the named actions on the content at the supplied
     *         path in the given workspace within the repository, or false otherwise
     */
    boolean hasPermission( ExecutionContext context,
                           String repositoryName,
                           String repositorySourceName,
                           String workspaceName,
                           Path path,
                           String... actions );
}
Copy to Clipboard Toggle word wrap
You can have your SecurityContext implementation also implement this interface, and return true whenever the session is allows to perform the requested operations.

15.1.3. The AdvancedAuthorizationProvider Interface

The hierarchical database uses its org.modeshape.jcr.security.AdvancedAuthorizationProvider interface to determine whether a Session has the appropriate privileges to perform reads and writes.
/**
 * An interface that can authorize access to specific resources within repositories. Unlike the more basic and simpl
 * AuthenticationProvider, this interface allows an implementation to get at additional information with each call to
 * hasPermission(Context, Path, String...).
 *
 * In particular, the supplied Context instance contains the Session that is calling this provider, allowing the
 * provider implementation to access authorization-specific content within the repository to determine permissions for other
 * repository content.
 *
 * In these cases, calls to the session to access nodes will result in their own calls to hasPermission(Context, Path, String...).
 * Therefore, such implementations need to handle these special authorization-specific content permissions in an explicit fashion.
 * It is also adviced that such providers cache as much of the authorization-specifc content as possible, as the 
 * hasPermission(Context, Path, String...) method is called frequently.
 */
public interface AdvancedAuthorizationProvider {

    /**
     * Determine if the supplied execution context has permission for all of the named actions in the given context. If not all
     * actions are allowed, the method returns false.
     *
     * @param context the context in which the subject is performing the actions on the supplied workspace
     * @param absPath the absolute path on which the actions are occurring, or null if the permissions are at the workspace-level
     * @param actions the list of {@link ModeShapePermissions actions} to check
     * @return true if the subject has privilege to perform all of the named actions on the content at the supplied path in the
     *         given workspace within the repository, or false otherwise
     */
    boolean hasPermission( Context context,
                           Path absPath,
                           String... actions );
}
Copy to Clipboard Toggle word wrap
where Context is a new nested interface nested in AdvancedAuthorizationProvider :
    /**
     * The context in which the calling session is operating, and which contains session-related information that a provider
     * implementation may find useful.
     */
    public static interface Context {
        /**
         * Get the execution context in which this session is running.
         *
         * @return the session's execution context; never null
         */
        public ExecutionContext getExecutionContext();

        /**
         * Get the session that is requesting this authorization provider to
         * {@link AdvancedAuthorizationProvider#hasPermission(Context, Path, String...) determine permissions}. Provider
         * implementations are free to use the session to access nodes <i>other</i> than those for which permissions are being
         * determined. For example, the implementation may access other <i>authorization-related content</i> inside the same
         * repository. Just be aware that such accesses will generate additional calls to the
         * {@link AdvancedAuthorizationProvider#hasPermission(Context, Path, String...)} method.
         *
         * @return the session; never null
         */
        public Session getSession();

        /**
         * Get the name of the repository that is being accessed.
         *
         * @return the repository name; never null
         */
        public String getRepositoryName();

        /**
         * Get the name of the repository workspace that is being accessed.
         *
         * @return the workspace name; never null
         */
        public String getWorkspaceName();
    }
Copy to Clipboard Toggle word wrap
You can have your SecurityContext implementation also implement this interface, and return true whenever the session is allows to perform the requested operations.

15.1.4. Configure a Repository to Use Your Custom Modules

Once you've implemented the interfaces and placed the classes on the classpath, all you have to do is then configure your repositories to use your modules. As noted in the "configuration overview" , there is a nested document in the JSON configuration file in the security field, and this section lists the authentication module implementations in the order that they should be used . For example:
    ...
    "security" : {
        "anonymous" : {
            "username" : "<anonymous>",
            "roles" : ["readonly","readwrite","admin"],
            "useOnFailedLogin" : false
        },
        "providers" : [
            {
                "name" : "My Custom Security Provider",
                "classname" : "com.example.MyAuthenticationProvider",
            },
            {
                "classname" : "JAAS",
                "policyName" : "modeshape-jcr",
            }
        ]
    },
    ...
Copy to Clipboard Toggle word wrap
This configuration enables the use of anonymous logins (although it disables a failed authentication attempt from downgrading to an anonymous session with the useOnFailedLogin as false ), and configures two authentication providers: the MyAuthenticationProvider implementation will be used first, and if that does not authenticate the repository will delegate to the built-in JAAS provider. (Note that built-in providers can be referenced with an alias in the classname field rather than the fully-qualified classname.) Anonymous authentication is always performed last.
맨 위로 이동
Red Hat logoGithubredditYoutubeTwitter

자세한 정보

평가판, 구매 및 판매

커뮤니티

Red Hat 문서 정보

Red Hat을 사용하는 고객은 신뢰할 수 있는 콘텐츠가 포함된 제품과 서비스를 통해 혁신하고 목표를 달성할 수 있습니다. 최신 업데이트를 확인하세요.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서, 웹 속성에서 문제가 있는 언어를 교체하기 위해 최선을 다하고 있습니다. 자세한 내용은 다음을 참조하세요.Red Hat 블로그.

Red Hat 소개

Red Hat은 기업이 핵심 데이터 센터에서 네트워크 에지에 이르기까지 플랫폼과 환경 전반에서 더 쉽게 작업할 수 있도록 강화된 솔루션을 제공합니다.

Theme

© 2025 Red Hat