Caso os módulos de logon incluídos no framework do JBossSX não funcionarem no seu ambiente de segurança, você pode gravar sua própria implantação do módulo de logon personalizado. O JaasSecurityManager requer um padrão de uso particular do conjunto de principais Subject. Você deve entender os recursos da classe de informação da classe do Sujeito JAAS e o uso esperado desses recursos para gravar um módulo de logon que funciona com o JaasSecurityManager.
Esta seção examina essas solicitações e introduz duas implantações LoginModule básicas abstratas que podem ajudá-lo a implantar os módulos de logon personalizados.
Você pode obter a informação associada com o Subject pelo uso dos seguintes métodos:
java.util.Set getPrincipals()
java.util.Set getPrincipals(java.lang.Class c)
java.util.Set getPrivateCredentials()
java.util.Set getPrivateCredentials(java.lang.Class c)
java.util.Set getPublicCredentials()
java.util.Set getPublicCredentials(java.lang.Class c)
java.util.Set getPrincipals()
java.util.Set getPrincipals(java.lang.Class c)
java.util.Set getPrivateCredentials()
java.util.Set getPrivateCredentials(java.lang.Class c)
java.util.Set getPublicCredentials()
java.util.Set getPublicCredentials(java.lang.Class c)
Copy to ClipboardCopied!Toggle word wrapToggle overflow
O JBossSX selecionou a escolha mais lógica: os conjuntos de principais obtidos através do getPrincipals() e getPrincipals(java.lang.Class) para as identidades e funções do Subject. Segue abaixo o uso padrão:
As identidades do usuário (por exemplo: nome do usuário, número de segurança social e ID do empregado) conforme armazenado com os objetos java.security.Principal no conjunto SubjectPrincipals. A implementação Principal que representa a identidade do usuário deve basear-se nas comparações e igualdade do nome do principal. Uma implantação útil está disponível como a classe org.jboss.security.SimplePrincipal. Outras instâncias Principal podem ser adicionadas ao conjunto SubjectPrincipals conforme seja necessário.
As funções determinadas do usuário estão também armazenadas no conjunto Principals e estão agrupadas nos conjuntos de função nomeados usando as instâncias java.security.acl.Group. A interface Group define uma coleção de Principals e/ou Groups, além de ser uma sub-interface do java.security.Principal.
Qualquer número de conjuntos de funções podem ser determinados a um Subject.
O framework do JBossSX usa dois conjuntos de funções bem conhecidos pelos nomes de Roles e CallerPrincipal.
O grupo Roles é uma coleção de Principals para funções nomeadas conforme o domínio do aplicativo pelo qual o Subject é autenticado. Este conjunto de função é usado por métodos como o EJBContext.isCallerInRole(String), em que os EJBs podem usar para verificar se o chamador atual pertence à função do domínio do aplicativo nomeado. A lógica do interceptor de segurança que executa as checagens de permissão do método usa também este conjunto de função.
O CallerPrincipalGroup consiste da identidade Principal única determinada ao usuário no domínio do aplicativo. O método EJBContext.getCallerPrincipal() usa o CallerPrincipal para permitir que o domínio do aplicativo realize o mapeamento a partir da identidade do ambiente de operação à identidade do usuário adequada ao aplicativo. Caso o Subject não possua um CallerPrincipalGroup, a identidade de aplicativo é o mesmo como a identidade de ambiente operacional.
Copiar o linkLink copiado para a área de transferência!
O JBossSX inclui os módulos de logon que preenchem o Subject autenticado com o padrão de modelo que reforça o uso do Subject correto, com o objetivo de simplificar a implantação correta do uso padrão descrito na Seção 12.2, “Módulos Personalizados”.
AbstractServerLoginModule
O módulo mais genérico dos dois é a classe org.jboss.security.auth.spi.AbstractServerLoginModule.
Ele fornece uma implantação da interface javax.security.auth.spi.LoginModule e oferece métodos abstratos para as tarefas chave específicas à infra-estrutura de segurança do ambiente. Os detalhes chave da classe estão descritos no Exemplo 12.9, “Fragmento da Classe AbstractServerLoginModule”. Os comentários do JavaDoc destacam as responsabilidades das sub-classes.
Importante
A variável da instância loginOk é experimental. Ela deve ser configurada para true, caso o logon for bem sucedido ou false por qualquer sub-classes que substituem o método de logon. Caso esta variável for incorretamente usada, o método de confirmação não atualizará corretamente o assunto.
O rastreamento da fase de logon permite que módulos de logon sejam encadeados com os avisos de controle. Os avisos de controle não requerem que os módulos de logon sejam bem sucedidos como parte do processo de autenticação.
Exemplo 12.9. Fragmento da Classe AbstractServerLoginModule
package org.jboss.security.auth.spi;
/**
* This class implements the common functionality required for a JAAS
* server-side LoginModule and implements the JBossSX standard
* Subject usage pattern of storing identities and roles. Subclass
* this module to create your own custom LoginModule and override the
* login(), getRoleSets(), and getIdentity() methods.
*/
public abstract class AbstractServerLoginModule
implements javax.security.auth.spi.LoginModule
{
protected Subject subject;
protected CallbackHandler callbackHandler;
protected Map sharedState;
protected Map options;
protected Logger log;
/** Flag indicating if the shared credential should be used */
protected boolean useFirstPass;
/**
* Flag indicating if the login phase succeeded. Subclasses that
* override the login method must set this to true on successful
* completion of login
*/
protected boolean loginOk;
// ...
/**
* Initialize the login module. This stores the subject,
* callbackHandler and sharedState and options for the login
* session. Subclasses should override if they need to process
* their own options. A call to super.initialize(...) must be
* made in the case of an override.
*
* <p>
* The options are checked for the <em>password-stacking</em> parameter.
* If this is set to "useFirstPass", the login identity will be taken from the
* <code>javax.security.auth.login.name</code> value of the sharedState map,
* and the proof of identity from the
* <code>javax.security.auth.login.password</code> value of the sharedState map.
*
* @param subject the Subject to update after a successful login.
* @param callbackHandler the CallbackHandler that will be used to obtain the
* the user identity and credentials.
* @param sharedState a Map shared between all configured login module instances
* @param options the parameters passed to the login module.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
// ...
}
/**
* Looks for javax.security.auth.login.name and
* javax.security.auth.login.password values in the sharedState
* map if the useFirstPass option was true and returns true if
* they exist. If they do not or are null this method returns
* false.
* Note that subclasses that override the login method
* must set the loginOk var to true if the login succeeds in
* order for the commit phase to populate the Subject. This
* implementation sets loginOk to true if the login() method
* returns true, otherwise, it sets loginOk to false.
*/
public boolean login()
throws LoginException
{
// ...
}
/**
* Overridden by subclasses to return the Principal that
* corresponds to the user primary identity.
*/
abstract protected Principal getIdentity();
/**
* Overridden by subclasses to return the Groups that correspond
* to the role sets assigned to the user. Subclasses should
* create at least a Group named "Roles" that contains the roles
* assigned to the user. A second common group is
* "CallerPrincipal," which provides the application identity of
* the user rather than the security domain identity.
*
* @return Group[] containing the sets of roles
*/
abstract protected Group[] getRoleSets() throws LoginException;
}
package org.jboss.security.auth.spi;
/**
* This class implements the common functionality required for a JAAS
* server-side LoginModule and implements the JBossSX standard
* Subject usage pattern of storing identities and roles. Subclass
* this module to create your own custom LoginModule and override the
* login(), getRoleSets(), and getIdentity() methods.
*/
public abstract class AbstractServerLoginModule
implements javax.security.auth.spi.LoginModule
{
protected Subject subject;
protected CallbackHandler callbackHandler;
protected Map sharedState;
protected Map options;
protected Logger log;
/** Flag indicating if the shared credential should be used */
protected boolean useFirstPass;
/**
* Flag indicating if the login phase succeeded. Subclasses that
* override the login method must set this to true on successful
* completion of login
*/
protected boolean loginOk;
// ...
/**
* Initialize the login module. This stores the subject,
* callbackHandler and sharedState and options for the login
* session. Subclasses should override if they need to process
* their own options. A call to super.initialize(...) must be
* made in the case of an override.
*
* <p>
* The options are checked for the <em>password-stacking</em> parameter.
* If this is set to "useFirstPass", the login identity will be taken from the
* <code>javax.security.auth.login.name</code> value of the sharedState map,
* and the proof of identity from the
* <code>javax.security.auth.login.password</code> value of the sharedState map.
*
* @param subject the Subject to update after a successful login.
* @param callbackHandler the CallbackHandler that will be used to obtain the
* the user identity and credentials.
* @param sharedState a Map shared between all configured login module instances
* @param options the parameters passed to the login module.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
// ...
}
/**
* Looks for javax.security.auth.login.name and
* javax.security.auth.login.password values in the sharedState
* map if the useFirstPass option was true and returns true if
* they exist. If they do not or are null this method returns
* false.
* Note that subclasses that override the login method
* must set the loginOk var to true if the login succeeds in
* order for the commit phase to populate the Subject. This
* implementation sets loginOk to true if the login() method
* returns true, otherwise, it sets loginOk to false.
*/
public boolean login()
throws LoginException
{
// ...
}
/**
* Overridden by subclasses to return the Principal that
* corresponds to the user primary identity.
*/
abstract protected Principal getIdentity();
/**
* Overridden by subclasses to return the Groups that correspond
* to the role sets assigned to the user. Subclasses should
* create at least a Group named "Roles" that contains the roles
* assigned to the user. A second common group is
* "CallerPrincipal," which provides the application identity of
* the user rather than the security domain identity.
*
* @return Group[] containing the sets of roles
*/
abstract protected Group[] getRoleSets() throws LoginException;
}
Copy to ClipboardCopied!Toggle word wrapToggle overflow
UsernamePasswordLoginModule
O segundo módulo de logon base abstrato apto para os módulos de logon personalizados é o org.jboss.security.auth.spi.UsernamePasswordLoginModule.
Este módulo de logon futuramente simplificará a implantação do módulo de logon reforçando um nome de usuário baseado na sequência assim como uma identidade de usuário e uma senha char[] conforme as credenciais de autenticação. Ele suporta também o mapeamento de usuários anônimos (indicados pelo nome do usuário e senha nulos) para um principal sem funções. Os detalhes chave da classe estão destacadas no fragmento da classe seguinte. Os comentários do JavaDoc detalham as responsabilidades das sub-classes.
Exemplo 12.10. Fragmento da Classe UsernamePasswordLoginModule
package org.jboss.security.auth.spi;
/**
* An abstract subclass of AbstractServerLoginModule that imposes a
* an identity == String username, credentials == String password
* view on the login process. Subclasses override the
* getUsersPassword() and getUsersRoles() methods to return the
* expected password and roles for the user.
*/
public abstract class UsernamePasswordLoginModule
extends AbstractServerLoginModule
{
/** The login identity */
private Principal identity;
/** The proof of login identity */
private char[] credential;
/** The principal to use when a null username and password are seen */
private Principal unauthenticatedIdentity;
/**
* The message digest algorithm used to hash passwords. If null then
* plain passwords will be used. */
private String hashAlgorithm = null;
/**
* The name of the charset/encoding to use when converting the
* password String to a byte array. Default is the platform's
* default encoding.
*/
private String hashCharset = null;
/** The string encoding format to use. Defaults to base64. */
private String hashEncoding = null;
// ...
/**
* Override the superclass method to look for an
* unauthenticatedIdentity property. This method first invokes
* the super version.
*
* @param options,
* @option unauthenticatedIdentity: the name of the principal to
* assign and authenticate when a null username and password are
* seen.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
super.initialize(subject, callbackHandler, sharedState,
options);
// Check for unauthenticatedIdentity option.
Object option = options.get("unauthenticatedIdentity");
String name = (String) option;
if (name != null) {
unauthenticatedIdentity = new SimplePrincipal(name);
}
}
// ...
/**
* A hook that allows subclasses to change the validation of the
* input password against the expected password. This version
* checks that neither inputPassword or expectedPassword are null
* and that inputPassword.equals(expectedPassword) is true;
*
* @return true if the inputPassword is valid, false otherwise.
*/
protected boolean validatePassword(String inputPassword,
String expectedPassword)
{
if (inputPassword == null || expectedPassword == null) {
return false;
}
return inputPassword.equals(expectedPassword);
}
/**
* Get the expected password for the current username available
* via the getUsername() method. This is called from within the
* login() method after the CallbackHandler has returned the
* username and candidate password.
*
* @return the valid password String
*/
abstract protected String getUsersPassword()
throws LoginException;
}
package org.jboss.security.auth.spi;
/**
* An abstract subclass of AbstractServerLoginModule that imposes a
* an identity == String username, credentials == String password
* view on the login process. Subclasses override the
* getUsersPassword() and getUsersRoles() methods to return the
* expected password and roles for the user.
*/
public abstract class UsernamePasswordLoginModule
extends AbstractServerLoginModule
{
/** The login identity */
private Principal identity;
/** The proof of login identity */
private char[] credential;
/** The principal to use when a null username and password are seen */
private Principal unauthenticatedIdentity;
/**
* The message digest algorithm used to hash passwords. If null then
* plain passwords will be used. */
private String hashAlgorithm = null;
/**
* The name of the charset/encoding to use when converting the
* password String to a byte array. Default is the platform's
* default encoding.
*/
private String hashCharset = null;
/** The string encoding format to use. Defaults to base64. */
private String hashEncoding = null;
// ...
/**
* Override the superclass method to look for an
* unauthenticatedIdentity property. This method first invokes
* the super version.
*
* @param options,
* @option unauthenticatedIdentity: the name of the principal to
* assign and authenticate when a null username and password are
* seen.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options)
{
super.initialize(subject, callbackHandler, sharedState,
options);
// Check for unauthenticatedIdentity option.
Object option = options.get("unauthenticatedIdentity");
String name = (String) option;
if (name != null) {
unauthenticatedIdentity = new SimplePrincipal(name);
}
}
// ...
/**
* A hook that allows subclasses to change the validation of the
* input password against the expected password. This version
* checks that neither inputPassword or expectedPassword are null
* and that inputPassword.equals(expectedPassword) is true;
*
* @return true if the inputPassword is valid, false otherwise.
*/
protected boolean validatePassword(String inputPassword,
String expectedPassword)
{
if (inputPassword == null || expectedPassword == null) {
return false;
}
return inputPassword.equals(expectedPassword);
}
/**
* Get the expected password for the current username available
* via the getUsername() method. This is called from within the
* login() method after the CallbackHandler has returned the
* username and candidate password.
*
* @return the valid password String
*/
abstract protected String getUsersPassword()
throws LoginException;
}
Copy to ClipboardCopied!Toggle word wrapToggle overflow
Módulos de Logon de Sub-classificação
A escolha da sub-classificação do AbstractServerLoginModule versus UsernamePasswordLoginModule simplesmente baseia-se no fato do nome do usuário e credenciais baseados na sequência a serem usados ou não pela tecnologia de autenticação que você está gravando para o módulo de logon. Caso a semântica baseada na sequência for válida, o UsernamePasswordLoginModule será sub-classificado. Do contrário, o AbstractServerLoginModule será sub-classificado.
Etapas de Sub-classificação
As etapas, pelas quais seu módulo de logon personalizado deve executar, dependem de qual classe de módulo de logon básico você escolher. Quando gravando o módulo de logon personalizado, que integra sua infra-estrutura de segurança, você deve iniciar pela sub-classificação do AbstractServerLoginModule ou UsernamePasswordLoginModule para garantir que seu módulo fornece a informação Principal autenticada pela forma esperada pelo gerenciador de segurança do JBossSX.
Você deverá substituir o seguinte na sub-classificação do AbstractServerLoginModule:
void initialize(Subject, CallbackHandler, Map, Map): caso você possua opções de personalização para análise.
boolean login(): para executar a atividade da autenticação. Certifique-se de configurar a variável da instância loginOk para verdadeiro caso o logon for bem sucedido e falso caso ele falhar.
Principal getIdentity(): para retornar o objeto Principal para o usuário autenticado pela etapa log().
Group[] getRoleSets(): para retornar pelo menos um Group nomeado Roles que contém as funções determinadas ao Principal autenticado durante o login(). O segundo Group comum é nomeado CallerPrincipal e fornece a identidade do aplicativo do usuário ao invés da identidade do domínio de segurança.
Você deverá substituir o seguinte, quando sub-classificando o UsernamePasswordLoginModule:
void initialize(Subject, CallbackHandler, Map, Map): caso você possua opções de personalização para análise.
Group[] getRoleSets(): para retornar pelo menos um Group nomeado Roles que contém as funções determinadas ao Principal autenticado durante o login(). O segundo Group comum é nomeado CallerPrincipal e fornece a identidade do aplicativo do usuário ao invés da identidade do domínio de segurança.
String getUsersPassword(): para retornar a senha esperada pelo nome de usuário atual disponível através do método getUsername(). O método getUsersPassword() é chamado a partir do login() após o callbackhandler retornar o nome do usuário e senha do candidato.
Ajudamos os usuários da Red Hat a inovar e atingir seus objetivos com nossos produtos e serviços com conteúdo em que podem confiar. Explore nossas atualizações recentes.
Tornando o open source mais inclusivo
A Red Hat está comprometida em substituir a linguagem problemática em nosso código, documentação e propriedades da web. Para mais detalhes veja o Blog da Red Hat.
Sobre a Red Hat
Fornecemos soluções robustas que facilitam o trabalho das empresas em plataformas e ambientes, desde o data center principal até a borda da rede.