Dieser Inhalt ist in der von Ihnen ausgewählten Sprache nicht verfügbar.
17.12. Example: Implement a Custom Provider
For example, let's imagine that our JCR application has its own authentication and authorization system. We can integrate with that by creating a new Credentials implementation called
MyAppCredentials to encapsulate any information needed by the authentication/authorization system, which we'll assume is accessed by a singleton class SecurityService. We can then implement AuthenticationProvider as follows:
public class MyAppAuthorizationProvider implements AuthorizationProvider {
private String appName;
/**
* Any public JavaBean properties can be set in the configuration
*/
public void setApplicationName( String appName ) {
this.appName = appName;
}
/**
* 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 that will be used for authorization throughout the Session.
* <p>
* 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.
* </p>
*
* @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's attributes; never null
* @return the execution context for the authenticated user, or null if
* this provider could not authenticate the user
*/
public ExecutionContext authenticate( Credentials credentials,
String repositoryName,
String workspaceName,
ExecutionContext repositoryContext,
Map<String,Object> sessionAttributes );
if ( credentials instanceof MyAppCredentials ) {
// Try to authenticate ...
MyAppCredentials appCreds = (MyAppCredentials)credentials;
String user = appCreds.getUser();
Object token = appCreds.getToken();
AppCreds creds = SecurityService.login(appName,user,token);
if ( creds != null ) {
// We're in ...
SecurityContext securityContext = new MyAppSecurityContext(creds);
return repositoryContext.with(securityContext);
}
}
return null;
}
}
public class MyAppAuthorizationProvider implements AuthorizationProvider {
private String appName;
/**
* Any public JavaBean properties can be set in the configuration
*/
public void setApplicationName( String appName ) {
this.appName = appName;
}
/**
* 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 that will be used for authorization throughout the Session.
* <p>
* 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.
* </p>
*
* @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's attributes; never null
* @return the execution context for the authenticated user, or null if
* this provider could not authenticate the user
*/
public ExecutionContext authenticate( Credentials credentials,
String repositoryName,
String workspaceName,
ExecutionContext repositoryContext,
Map<String,Object> sessionAttributes );
if ( credentials instanceof MyAppCredentials ) {
// Try to authenticate ...
MyAppCredentials appCreds = (MyAppCredentials)credentials;
String user = appCreds.getUser();
Object token = appCreds.getToken();
AppCreds creds = SecurityService.login(appName,user,token);
if ( creds != null ) {
// We're in ...
SecurityContext securityContext = new MyAppSecurityContext(creds);
return repositoryContext.with(securityContext);
}
}
return null;
}
}
where the
MyAppSecurityContext is as follows:
public class MyAppSecurityContext
implements SecurityContext, AuthorizationProvider {
private final AppCreds creds;
public MyAppSecurityContext( AppCreds creds ) {
this.creds = creds;
}
/**
* {@inheritDoc SecurityContext#getUserName()}
*
* @see SecurityContext#getUserName()
*/
public final String getUserName() {
return creds.getUser();
}
/**
* {@inheritDoc SecurityContext#hasRole(String)}
*
* @see SecurityContext#hasRole(String)
*/
public final boolean hasRole( String roleName ) {
// shouldn't be called since we've implemented AuthorizationProvider
return false;
}
/**
* {@inheritDoc}
*
* @see org.modeshape.graph.SecurityContext#logout()
*/
public void logout() {
creds.logout();
}
/**
* {@inheritDoc}
*
* @see org.modeshape.jcr.security.AuthorizationProvider.hasPermission
*/
public boolean hasPermission( ExecutionContext context,
String repositoryName,
String repositorySourceName,
String workspaceName,
Path path,
String... actions ) {
// This is imaginary and simplistic, but you'd implement any authorization logic here ...
return this.creds.isAuthorized(repositoryName,workspaceName,path);
}
}
public class MyAppSecurityContext
implements SecurityContext, AuthorizationProvider {
private final AppCreds creds;
public MyAppSecurityContext( AppCreds creds ) {
this.creds = creds;
}
/**
* {@inheritDoc SecurityContext#getUserName()}
*
* @see SecurityContext#getUserName()
*/
public final String getUserName() {
return creds.getUser();
}
/**
* {@inheritDoc SecurityContext#hasRole(String)}
*
* @see SecurityContext#hasRole(String)
*/
public final boolean hasRole( String roleName ) {
// shouldn't be called since we've implemented AuthorizationProvider
return false;
}
/**
* {@inheritDoc}
*
* @see org.modeshape.graph.SecurityContext#logout()
*/
public void logout() {
creds.logout();
}
/**
* {@inheritDoc}
*
* @see org.modeshape.jcr.security.AuthorizationProvider.hasPermission
*/
public boolean hasPermission( ExecutionContext context,
String repositoryName,
String repositorySourceName,
String workspaceName,
Path path,
String... actions ) {
// This is imaginary and simplistic, but you'd implement any authorization logic here ...
return this.creds.isAuthorized(repositoryName,workspaceName,path);
}
}
Then we just need to configure the Repository to use this provider. In the ModeShape configuration files, there is an optional "
mode:authenticationProviders" child element of "mode:repository", and within this fragment you can define zero or more authentication providers by specifying a name, the class, an optional description, and optionally any bean properties that should be called upon instantiation. (Note that the class will be instantiated only once per Repository instance). Here's an example configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:mode="http://www.modeshape.org/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0">
<mode:repositories>
<mode:repository jcr:name="MyApp Repository" mode:source="Store">
...
<mode:authenticationProviders>
<!-- Specify the providers in a manner similar to sequencer
definitions are defined -->
<mode:authenticationProvider jcr:name="CustomProviderA"
mode:classname="org.example.MyAppAuthorizationProvider">
<mode:description>My authentication provider</mode:description>
<!-- Set JavaBean properties on provider if needed -->
<mode:appName>MyAppName</mode:appName>
</mode:authenticationProvider>
...
</mode:authenticationProviders>
...
</mode:repository>
...
</mode:repositories>
...
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:mode="http://www.modeshape.org/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0">
<mode:repositories>
<mode:repository jcr:name="MyApp Repository" mode:source="Store">
...
<mode:authenticationProviders>
<!-- Specify the providers in a manner similar to sequencer
definitions are defined -->
<mode:authenticationProvider jcr:name="CustomProviderA"
mode:classname="org.example.MyAppAuthorizationProvider">
<mode:description>My authentication provider</mode:description>
<!-- Set JavaBean properties on provider if needed -->
<mode:appName>MyAppName</mode:appName>
</mode:authenticationProvider>
...
</mode:authenticationProviders>
...
</mode:repository>
...
</mode:repositories>
...
</configuration>