CCM NG: LoginConfig (JAAS)
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3526 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
1910d3d656
commit
c9b854a723
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (C) 2015 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package org.libreccm.core.authentication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.Configuration;
|
||||
|
||||
/**
|
||||
* Parses a string array/list of strings to create an configuration for JAAS.
|
||||
*
|
||||
* This class is based on the {@code com.arsdigita.kernel.security.LoginConfig}
|
||||
* class. The code itself has been heavily refactored using features like
|
||||
* Generics and other things added to the Java language and the Java Standard
|
||||
* Library in the last ten years since the original class was written.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class LoginConfig extends Configuration {
|
||||
|
||||
/**
|
||||
* Maps application names to {@code AppConfigurationEntry[]}.
|
||||
*
|
||||
* ToDo: To create a configuration this class parses strings. Of course the
|
||||
* parsing may fails. In this case the constructor throws an exception.
|
||||
* Throwing exceptions from a constructor is considered a bad practise
|
||||
* because this may leaves a party created object. Instead the better option
|
||||
* would be a factory method or a builder.
|
||||
*/
|
||||
private final Map<String, AppConfigurationEntry[]> appConfigs = new HashMap<>();
|
||||
|
||||
private LoginConfig() {
|
||||
//Nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new login configuration from a list of string. {@code Request}
|
||||
* and {@code Register} are mandatory contexts, WAF refuses to start if they
|
||||
* are not configured. Each login context can span multiple modules.
|
||||
*
|
||||
* The input list comprises of strings adhering to the following format:
|
||||
*
|
||||
* <pre>
|
||||
* context:moduleName:controlFlag[:option1[:option2[:...]]]
|
||||
* </pre>
|
||||
*
|
||||
* <dl>
|
||||
*
|
||||
* <dt>context</dt>
|
||||
* <dd>String</dd>
|
||||
*
|
||||
* <dt>moduleName</dt>
|
||||
* <dd>String</dd>
|
||||
*
|
||||
* <dt>controlFlag</dt>
|
||||
* <dd>"required"</dd>
|
||||
* <dd>"requisite"</dd>
|
||||
* <dd>"sufficient"</dd>
|
||||
* <dd>"optional"</dd>
|
||||
*
|
||||
* <dt>option</dt>
|
||||
* <dd>"key=value"</dd>
|
||||
* </dl>
|
||||
*
|
||||
* <p>
|
||||
* Example:</p>
|
||||
*
|
||||
* <pre>
|
||||
* Request:com.arsdigita.kernel.security.CredentialLoginModule:requisite:debug=true
|
||||
* Register:com.arsdigita.kernel.security.LocalLoginModule:requisite
|
||||
* Register:com.arsdigita.kernel.security.UserIDLoginModule:requisite
|
||||
* Register:com.arsdigita.kernel.security.CredentialLoginModule:optional
|
||||
* </pre>
|
||||
*
|
||||
* @param config The configuration in string format.
|
||||
*
|
||||
*/
|
||||
public LoginConfig(final List<String> config) {
|
||||
final Map<String, List<String>> contextConfigs = new HashMap<>();
|
||||
|
||||
for (String tuple : config) {
|
||||
final int pos = tuple.indexOf(':');
|
||||
final String context = tuple.substring(0, pos);
|
||||
final String moduleConfig = tuple.substring(pos + 1);
|
||||
final List<String> contextConfig = retrieveContextConfig(
|
||||
context, contextConfigs);
|
||||
|
||||
contextConfig.add(moduleConfig);
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, List<String>> entry : contextConfigs.
|
||||
entrySet()) {
|
||||
addAppConfig(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> retrieveContextConfig(
|
||||
final String context, final Map<String, List<String>> contextConfigs) {
|
||||
List<String> contextConfig = contextConfigs.get(context);
|
||||
|
||||
if (contextConfig == null) {
|
||||
contextConfig = new ArrayList<>();
|
||||
contextConfigs.put(context, contextConfig);
|
||||
}
|
||||
|
||||
return contextConfig;
|
||||
}
|
||||
|
||||
private void addAppConfig(final String name, final List<String> entries) {
|
||||
final AppConfigurationEntry[] configEntries
|
||||
= new AppConfigurationEntry[entries.size()];
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
final List<String> entry = Arrays.asList(entries.get(i).split(":"));
|
||||
configEntries[i] = loadAppConfigEntry(entry);
|
||||
|
||||
}
|
||||
appConfigs.put(name, configEntries);
|
||||
}
|
||||
|
||||
private AppConfigurationEntry loadAppConfigEntry(final List<String> entry) {
|
||||
if (entry.size() < 2) {
|
||||
throw new LoginConfigMalformedException("LoginConfig is malformed.");
|
||||
}
|
||||
|
||||
final String name = entry.get(0);
|
||||
final AppConfigurationEntry.LoginModuleControlFlag flag = parseFlag(
|
||||
entry.get(1));
|
||||
final Map<String, String> options = new HashMap<>();
|
||||
|
||||
if (entry.size() > 2) {
|
||||
for (int i = 2; i < entry.size(); i++) {
|
||||
addOption(entry.get(i), options);
|
||||
}
|
||||
}
|
||||
|
||||
return new AppConfigurationEntry(name, flag, options);
|
||||
}
|
||||
|
||||
private AppConfigurationEntry.LoginModuleControlFlag parseFlag(
|
||||
final String flagStr) {
|
||||
switch (flagStr) {
|
||||
case "REQUISITE":
|
||||
return AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
|
||||
|
||||
case "REQUIRED":
|
||||
return AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
|
||||
|
||||
case "SUFFICIENT":
|
||||
return AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
|
||||
|
||||
case "OPTIONAL":
|
||||
return AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
|
||||
|
||||
default:
|
||||
throw new LoginConfigMalformedException(String.format(
|
||||
"Unknown flag \"%s\". Valid flags are: REQUISITE, "
|
||||
+ "REQUIRED, SUFFICIENT, OPTIONAL",
|
||||
flagStr));
|
||||
}
|
||||
}
|
||||
|
||||
private void addOption(final String option,
|
||||
final Map<String, String> options) {
|
||||
final int index = option.indexOf('=');
|
||||
if (index == -1) {
|
||||
throw new LoginConfigMalformedException(String.format(
|
||||
"The option string \"%s\" is malformed.", option));
|
||||
}
|
||||
|
||||
final String key = option.substring(0, index);
|
||||
final String value = option.substring(index + 1);
|
||||
options.put(key, value);
|
||||
}
|
||||
|
||||
public static void foo(final LoginConfig config) {
|
||||
if (config.appConfigs.get("foo") != null) {
|
||||
config.appConfigs.remove("foo");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor taking an arrays of strings containing the
|
||||
* configuration. Internally this constructor converts the array to a list
|
||||
* and calls {@link #LoginConfig(java.util.List)}.
|
||||
*
|
||||
* @param config The configuration in string form.
|
||||
*
|
||||
* @see #LoginConfig(java.util.List)
|
||||
*/
|
||||
public LoginConfig(final String[] config) {
|
||||
this(Arrays.asList(config));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry(final String name) {
|
||||
return appConfigs.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
// Nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2015 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package org.libreccm.core.authentication;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class LoginConfigMalformedException extends RuntimeException {
|
||||
private static final long serialVersionUID = 8573796343232732323L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>NewException</code> without detail
|
||||
* message.
|
||||
*/
|
||||
public LoginConfigMalformedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>NewException</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public LoginConfigMalformedException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue