Java tutorial
/* Copyright (c) 2001 - 2013 OpenPlans - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.xml; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.geoserver.security.GeoServerUserGroupStore; import org.geoserver.security.KeyStoreProvider; import org.geoserver.security.config.FileBasedSecurityServiceConfig; import org.geoserver.security.config.SecurityNamedServiceConfig; import org.geoserver.security.config.SecurityUserGroupServiceConfig; import org.geoserver.security.impl.AbstractUserGroupService; import org.geoserver.security.impl.GeoServerUser; import org.geoserver.security.impl.GeoServerUserGroup; import org.geoserver.security.impl.Util; import org.geoserver.security.password.GeoServerPasswordEncoder; import org.geoserver.security.password.PasswordEncodingType; import org.geoserver.security.password.RandomPasswordProvider; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * @author christian * */ public class XMLUserGroupService extends AbstractUserGroupService { static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.security.xml"); protected DocumentBuilder builder; protected File userFile; /** * Validate against schema on load/store, * default = true; */ private boolean validatingXMLSchema = true; public XMLUserGroupService() throws IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setIgnoringComments(true); try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new IOException(e); } } @Override public void initializeFromConfig(SecurityNamedServiceConfig config) throws IOException { this.name = config.getName(); validatingXMLSchema = false; passwordEncoderName = ((SecurityUserGroupServiceConfig) config).getPasswordEncoderName(); passwordValidatorName = ((SecurityUserGroupServiceConfig) config).getPasswordPolicyName(); GeoServerPasswordEncoder enc = getSecurityManager().loadPasswordEncoder(passwordEncoderName); if (enc.getEncodingType() == PasswordEncodingType.ENCRYPT) { KeyStoreProvider prov = getSecurityManager().getKeyStoreProvider(); String alias = prov.aliasForGroupService(name); if (prov.containsAlias(alias) == false) { prov.setUserGroupKey(name, getSecurityManager().getRandomPassworddProvider().getRandomPasswordWithDefaultLength()); prov.storeKeyStore(); } } enc.initializeFor(this); if (config instanceof XMLSecurityServiceConfig) { validatingXMLSchema = ((XMLSecurityServiceConfig) config).isValidating(); // copy schema file File xsdFile = new File(getConfigRoot(), XMLConstants.FILE_UR_SCHEMA); if (xsdFile.exists() == false) { FileUtils.copyURLToFile(getClass().getResource(XMLConstants.FILE_UR_SCHEMA), xsdFile); } } if (config instanceof FileBasedSecurityServiceConfig) { String fileName = ((FileBasedSecurityServiceConfig) config).getFileName(); userFile = new File(fileName); if (userFile.isAbsolute() == false) { userFile = new File(getConfigRoot(), fileName); } if (userFile.exists() == false) { FileUtils.copyURLToFile(getClass().getResource("usersTemplate.xml"), userFile); } } else { throw new IOException("Cannot initialize from " + config.getClass().getName()); } deserialize(); } @Override public boolean canCreateStore() { return true; } @Override public GeoServerUserGroupStore createStore() throws IOException { XMLUserGroupStore store = new XMLUserGroupStore(); store.initializeFromService(this); return store; } public boolean isValidatingXMLSchema() { return validatingXMLSchema; } public void setValidatingXMLSchema(boolean validatingXMLSchema) { this.validatingXMLSchema = validatingXMLSchema; } /* (non-Javadoc) * @see org.geoserver.security.impl.AbstractUserGroupService#deserialize() */ @Override protected void deserialize() throws IOException { try { Document doc = null; FileInputStream is = null; try { is = new FileInputStream(userFile); doc = builder.parse(is); } catch (SAXException e) { throw new IOException(e); } finally { IOUtils.closeQuietly(is); } if (isValidatingXMLSchema()) { XMLValidator.Singleton.validateUserGroupRegistry(doc); } XPathExpression expr = XMLXpathFactory.Singleton.getVersionExpressionUR(); String versionNummer = expr.evaluate(doc); UserGroupXMLXpath xmlXPath = XMLXpathFactory.Singleton.getUserGroupXMLXpath(versionNummer); clearMaps(); NodeList userNodes = (NodeList) xmlXPath.getUserListExpression().evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < userNodes.getLength(); i++) { Node userNode = userNodes.item(i); boolean userEnabled = Util.convertToBoolean(xmlXPath.getUserEnabledExpression().evaluate(userNode), true); String userPassword = null; //there doesn't seem to be a way to check for existence of an attribute vs an // attribute being empty, so we check the attribute manually if (userNode.getAttributes().getNamedItem(XMLConstants.A_USER_PASSWORD_UR) != null) { userPassword = xmlXPath.getUserPasswordExpression().evaluate(userNode); } String userName = xmlXPath.getUserNameExpression().evaluate(userNode); NodeList propertyNodes = (NodeList) xmlXPath.getUserPropertiesExpression().evaluate(userNode, XPathConstants.NODESET); Properties userProps = new Properties(); for (int j = 0; j < propertyNodes.getLength(); j++) { Node propertyNode = propertyNodes.item(j); String propertyName = xmlXPath.getPropertyNameExpression().evaluate(propertyNode); String propertyValue = xmlXPath.getPropertyValueExpression().evaluate(propertyNode); userProps.put(propertyName, propertyValue); } GeoServerUser user = createUserObject(userName, userPassword, userEnabled); helper.userMap.put(user.getUsername(), user); user.getProperties().clear(); // set properties for (Object key : userProps.keySet()) { user.getProperties().put(key, userProps.get(key)); SortedSet<GeoServerUser> propUsers = helper.propertyMap.get(key); if (propUsers == null) { propUsers = new TreeSet<GeoServerUser>(); helper.propertyMap.put((String) key, propUsers); } propUsers.add(user); } } NodeList groupNodes = (NodeList) xmlXPath.getGroupListExpression().evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < groupNodes.getLength(); i++) { Node groupNode = groupNodes.item(i); String groupName = xmlXPath.getGroupNameExpression().evaluate(groupNode); boolean groupEnabled = Util .convertToBoolean(xmlXPath.getGroupEnabledExpression().evaluate(groupNode), true); GeoServerUserGroup group = createGroupObject(groupName, groupEnabled); helper.groupMap.put(groupName, group); NodeList memberNodes = (NodeList) xmlXPath.getGroupMemberListExpression().evaluate(groupNode, XPathConstants.NODESET); for (int j = 0; j < memberNodes.getLength(); j++) { Node memberNode = memberNodes.item(j); String memberName = xmlXPath.getGroupMemberNameExpression().evaluate(memberNode); GeoServerUser member = helper.userMap.get(memberName); SortedSet<GeoServerUser> members = helper.group_userMap.get(group); if (members == null) { members = new TreeSet<GeoServerUser>(); helper.group_userMap.put(group, members); } members.add(member); SortedSet<GeoServerUserGroup> userGroups = helper.user_groupMap.get(member); if (userGroups == null) { userGroups = new TreeSet<GeoServerUserGroup>(); helper.user_groupMap.put(member, userGroups); } userGroups.add(group); } } } catch (XPathExpressionException ex) { throw new IOException(ex); } } @Override public GeoServerUser createUserObject(String username, String password, boolean isEnabled) throws IOException { XMLGeoserverUser user = new XMLGeoserverUser(username); user.setEnabled(isEnabled); user.setPassword(password); return user; } }