📄 htpasswd.java
字号:
/* HtPasswd.java 16/11/01 19:27 cyrille@ktaland.com*/package org.xmlBlaster.authentication.plugins.htpasswd;import org.xmlBlaster.authentication.SessionInfo;import org.xmlBlaster.authentication.plugins.DataHolder;import org.xmlBlaster.authentication.plugins.SessionHolder;import org.xmlBlaster.util.FileLocator;import org.xmlBlaster.util.SessionName;import org.xmlBlaster.util.StringPairTokenizer;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.def.Constants;import org.xmlBlaster.util.def.ErrorCode;import org.xmlBlaster.util.def.MethodName;import java.util.logging.Logger;import java.util.logging.Level;import java.io.* ;import java.util.HashSet;import java.util.Hashtable ;import java.util.Enumeration ;import java.util.Map;import java.util.Set;import java.util.Vector;//import org.xmlBlaster.authentication.plugins.htpasswd.jcrypt;/** * In xmlBlaster.properties add :<br> * Security.Server.Plugin.htpasswd.secretfile=${user.home}${file.separator}xmlBlaster.htpasswd * <p /> * Changes: astelzl@avitech.de<br /> * There can be three cases for authentication: * <ol> * <li>in xmlBlaster.properties the property Security.Server.Plugin.htpasswd.allowPartialUsername is true -> * the user is authenticated with the right password and an username which begins with the specified username * </li> * <li>allowPartialUsername is false -> * the user is just authenticated if the username and password in the password file * exactly equals the specifications at connection to the xmlBlaster * </li>it is possible that the password file just contains a * instead * of (username,password) tuples -> any username and password combination is authenticated * Same if Security.Server.Plugin.htpasswd.secretfile=NONE * </li> * </ol> * <p /> * Changes: mr@marcelruff.info<br /> * Added simple authorization support. * <p /> * NOTE: Currently the htpasswd file is reread every time a client logs in (see Session.java new HtPasswd()) * we should change this to check the timestamp of the file. * On client - reconnect there is no reload forced. * <p /> * Switch on logging with: -logging/org.xmlBlaster.authentication.plugins.htpasswd FINEST * @author <a href="mailto:cyrille@ktaland.com">Cyrille Giquello</a> 16/11/01 09:06 * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/security.htpasswd.html">The security.htpasswd requirement</a> */public class HtPasswd { private static final String ME = "HtPasswd"; protected Global glob; private static Logger log = Logger.getLogger(HtPasswd.class.getName()); protected final int ALLOW_PARTIAL_USERNAME = 1; protected final int FULL_USERNAME = 2; protected final int SWITCH_OFF = 3; protected int useFullUsername = ALLOW_PARTIAL_USERNAME; protected String htpasswdFilename = null ; /* Key is user name, values is the Container with encrypted password */ protected Hashtable htpasswdMap = null ; protected Hashtable containerCache = new Hashtable(); protected long lastModified = -1L; private static boolean first = true; private static boolean firstWild = true; private class Container { public String userName=""; public String password=""; public Map allowedMethodNames; // contains MethodNames for authorization as key, set of topic oids as value public Container(String user) { this.userName = user; } public String toString() { String ret = "user='" + userName + "' passwd='" + password + "'"; if (this.allowedMethodNames != null) ret += " allowedMethods=" + MethodName.toString((MethodName[])this.allowedMethodNames.keySet().toArray(new MethodName[this.allowedMethodNames.size()])); return ret; } public boolean isAllowed(MethodName methodName, String topicOid) { if (this.allowedMethodNames == null) return true; Set oidSet = (Set)this.allowedMethodNames.get(methodName); if (oidSet == null) return false; if (topicOid == null) return true; if (oidSet.size() == 0) return true; return oidSet.contains(topicOid.trim()); } } /** * Check password * 16/11/01 19:36 mad@ktaland.com */ public HtPasswd(Global glob) throws XmlBlasterException { this.glob = glob; htpasswdFilename = glob.getProperty().get("Security.Server.Plugin.htpasswd.secretfile", "NONE" ); boolean allowPartialUsername = glob.getProperty().get("Security.Server.Plugin.htpasswd.allowPartialUsername", false); if ( allowPartialUsername ) { useFullUsername = ALLOW_PARTIAL_USERNAME; if (log.isLoggable(Level.FINE)) log.fine("Login names are searched with 'startswith' mode in '" + htpasswdFilename + "'."); } else { useFullUsername = FULL_USERNAME; if (log.isLoggable(Level.FINE)) log.fine( "contructor(" + htpasswdFilename + ") allowPartialUsername=false" ); } if (htpasswdFilename != null && htpasswdFilename.equals("NONE")) { useFullUsername = SWITCH_OFF; if (first) { log.warning("Security risk, no access control: The passwd file is switched off with 'Security.Server.Plugin.htpasswd.secretfile=NONE'"); first = false; } return; } if (log.isLoggable(Level.FINE)) log.fine( "contructor(" + htpasswdFilename + ") " ); if( readHtpasswordFile( htpasswdFilename ) ){ } }//HtPassWd /** * Helper class for checkPassword in the case of startWith(username) -> * here more usernames of the hashtable can be right * @param userPassword password in plaintext * @param fileEncodedPass vector of passwords where usernames match with the specified beginning of an username * @return true if any one matches */ private boolean checkDetailed(String userPassword, Vector fileEncodedPass) { if (log.isLoggable(Level.FINE)) log.fine("Comparing '" + userPassword + "' in " + fileEncodedPass.size() + " possibilities"); String encoded = null,salt,userEncoded; for (Enumeration e = fileEncodedPass.elements();e.hasMoreElements();) { Container container = (Container)e.nextElement(); encoded = container.password; if (encoded != null && encoded.length() == 0) return true; // empty password "joe::" if (encoded != null && encoded.length() > 2) { salt = encoded.substring(0,2); userEncoded = jcrypt.crypt(salt,userPassword); if (log.isLoggable(Level.FINE)) log.fine("Comparing '" + userEncoded + "' with passwd entry '" + encoded + "'"); if ( userEncoded.trim().equals(encoded.trim()) ) return true; } } return false; } /** * Check password * @param password The clear text password * @return true The password is valid */ public boolean checkPassword( String userName, String userPassword ) throws XmlBlasterException { //if (log.TRACE && htpasswd!=null) log.trace(ME, "Checking userName=" + userName + " passwd='" + userPassword + "' in " + htpasswd.size() + " entries, mode=" + useFullUsername + " ..."); if ( useFullUsername == SWITCH_OFF ) { return true; } if( this.htpasswdMap != null && userName!=null && userPassword!=null ){ //find user in Hashtable htpasswd Vector pws = lookup(userName); return checkDetailed(userPassword,pws); } return false; }//checkPassword /** * Lookup userName in password file * @param userName * @return A list containing Container instances (matching the userName) */ private Vector lookup(String userName) { Vector pws = new Vector(); if (userName == null) return pws; //find user in Hashtable htpasswd String key; boolean found = false; if ( useFullUsername == FULL_USERNAME ) { Container container = (Container)this.htpasswdMap.get(userName); if (container != null) { pws.addElement(container); found = true; } } else { // ALLOW_PARTIAL_USERNAME for (Enumeration e = this.htpasswdMap.keys();e.hasMoreElements() ; ) { key = (String)e.nextElement(); if (log.isLoggable(Level.FINE)) log.fine("Checking userName=" + userName + " with key='" + key + "'"); if (userName.startsWith(key) || userName.endsWith(key)) { Container container = (Container)this.htpasswdMap.get(key); pws.addElement(container); found = true; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -