📄 digestauthfilter.java
字号:
// DigestAuthFilter.java// $Id: DigestAuthFilter.java,v 1.7 2000/12/08 12:28:56 ylafon Exp $// (c) COPYRIGHT MIT, INRIA and Keio, 1999.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.jigsaw.auth;import java.util.Date;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import org.w3c.tools.resources.Attribute;import org.w3c.tools.resources.AttributeRegistry;import org.w3c.tools.resources.FramedResource;import org.w3c.tools.resources.IntegerAttribute;import org.w3c.tools.resources.InvalidResourceException;import org.w3c.tools.resources.ProtocolException;import org.w3c.tools.resources.ReplyInterface;import org.w3c.tools.resources.RequestInterface;import org.w3c.tools.resources.ResourceReference;import org.w3c.tools.resources.StringArrayAttribute;import org.w3c.tools.resources.StringAttribute;import org.w3c.jigsaw.http.Client;import org.w3c.jigsaw.http.HTTPException;import org.w3c.jigsaw.http.Reply;import org.w3c.jigsaw.http.Request;import org.w3c.jigsaw.http.httpd;import org.w3c.jigsaw.html.HtmlGenerator;import org.w3c.www.http.HTTP;import org.w3c.www.http.HttpChallenge;import org.w3c.www.http.HttpCredential;import org.w3c.www.http.HttpFactory;import org.w3c.jigsaw.frames.HTTPFrame;import org.w3c.util.StringUtils;import org.w3c.tools.resources.ProtocolException;/** * Internal exception class */class DigestAuthFilterException extends Exception { DigestAuthFilterException (String msg) { super (msg); }}/** * DigestAuthFilter provides for both IP and digest authentication. * This is really a first implementation. It looses on several points: * <ul> * <li>AuthUser instances, being a subclass of resource dump their classes * along with their attributes, although here we know that they will all * be instances of AuthUser. * <li>The way the ipmatcher is maintained doesn't make much sense. * <li>The way groups are handled is no good. * <li>The SimpleResourceStore is not an adequat store for the user database, * it should rather use the jdbmResourceStore (not written yet). * </ul> * However, this provides for the digest functionnalities. */public class DigestAuthFilter extends AuthFilter { public class DigestAuthContext { String dac_user = null; String dac_realm = null; String dac_nonce = null; String dac_uri = null; String dac_response = null; String dac_algorithm = null; String dac_method = null; boolean stale = false; // qop and nc may be added at some point // maybe not as it implies session tracking DigestAuthContext (Request request) throws DigestAuthFilterException, ProtocolException { HttpCredential credential = null; credential = (request.isProxy() ? request.getProxyAuthorization() : request.getAuthorization()); if ( ! credential.getScheme().equalsIgnoreCase("Digest") ) { String msg = ("Invalid authentication scheme \"" + credential.getScheme() + " expecting \"Digest\""); throw new DigestAuthFilterException (msg) ; } // now split things and decode things dac_user = credential.getAuthParameter("username"); dac_uri = credential.getAuthParameter("uri"); dac_response = credential.getAuthParameter("response"); dac_realm = credential.getAuthParameter("realm"); dac_method = request.getMethod(); dac_nonce = credential.getAuthParameter("nonce"); if (dac_user == null || dac_uri == null || dac_response == null || dac_realm == null) { String msg = ("Invalid authentication header"); throw new DigestAuthFilterException(msg); } } boolean authenticate(String username, String realm, String passwd) { stale = false; if (!dac_user.equals(username)) return false; if (!dac_realm.equals(realm)) return false; if (dac_algorithm != null && !dac_algorithm.equals(getAlgorithm())) return false; if (!dac_nonce.equals(nonce)) { if (!dac_nonce.equals(old_nonce)) { // check if the user knows the right passwd String a1, a2, ha1, ha2; a1 = username + ":" + realm + ":" + passwd; a2 = dac_method + ":" + dac_uri; MessageDigest md = null; try { md = MessageDigest.getInstance(getAlgorithm()); } catch (NoSuchAlgorithmException algex) { // fatal error, can't authenticate return false; } md.update(a1.getBytes()); ha1 = StringUtils.toHexString(md.digest()); md.reset(); md.update(a2.getBytes()); ha2 = StringUtils.toHexString(md.digest()); md.reset(); String kd, hkd; // KD( H(A1), unq(nonce-value) ":" H(A2) kd = ha1 + ":" + dac_nonce + ":" + ha2; md.update(kd.getBytes()); hkd = StringUtils.toHexString(md.digest()); stale = hkd.equals(dac_response); return false; } else stale = true; } // basic things have been checked... now try the real thing String a1, a2, ha1, ha2; a1 = username + ":" + realm + ":" + passwd; a2 = dac_method + ":" + dac_uri; MessageDigest md = null; try { md = MessageDigest.getInstance(getAlgorithm()); } catch (NoSuchAlgorithmException algex) { // fatal error, can't authenticate return false; } md.update(a1.getBytes()); ha1 = StringUtils.toHexString(md.digest()); md.reset(); md.update(a2.getBytes()); ha2 = StringUtils.toHexString(md.digest()); md.reset(); String kd, hkd; if (stale) // KD( H(A1), unq(nonce-value) ":" H(A2) kd = ha1 + ":" + old_nonce + ":" + ha2; else kd = ha1 + ":" + nonce + ":" + ha2; md.update(kd.getBytes()); hkd = StringUtils.toHexString(md.digest()); if (!hkd.equals(dac_response)) return false; // yeah!!! return true; } } /** * Attribute index - The list of allowed users. */ protected static int ATTR_ALLOWED_USERS = -1 ; /** * Attribute index - The list of allowed groups. */ protected static int ATTR_ALLOWED_GROUPS = -1 ; /** * Attribute index - The algorithm used */ protected static int ATTR_ALGORITHM = -1 ; /** * Attribute index - The nonce time to live (in seconds) */ protected static int ATTR_NONCE_TTL = -1 ; static { Attribute a = null ; Class c = null ; try { c = Class.forName("org.w3c.jigsaw.auth.DigestAuthFilter"); } catch (Exception ex) { ex.printStackTrace() ; System.exit(1) ; } // The list of allowed users a = new StringArrayAttribute("users" , null , Attribute.EDITABLE) ; ATTR_ALLOWED_USERS = AttributeRegistry.registerAttribute(c, a) ; // The list of allowed groups: a = new StringArrayAttribute("groups" , null , Attribute.EDITABLE); ATTR_ALLOWED_GROUPS = AttributeRegistry.registerAttribute(c, a) ; // The algorithm used for digest and checksum a = new StringAttribute("algorithm" , null , Attribute.EDITABLE); ATTR_ALGORITHM = AttributeRegistry.registerAttribute(c, a) ; a = new IntegerAttribute("nonce_ttl" , new Integer(300) , Attribute.EDITABLE); ATTR_NONCE_TTL = AttributeRegistry.registerAttribute(c, a) ; } /** * The catalog of realms that make our scope. */ protected RealmsCatalog catalog = null ; /** * Our associated realm. */ protected ResourceReference rr_realm = null ; /** * The nam of the realm we cache in <code>realm</code>. */ protected String loaded_realm = null ; /** * The challenge to issue to any client for Digest Authentication. */ protected HttpChallenge challenge = null; /** * The nonce value of the digest, changed every X mn */ protected String nonce = null; /** * The previous nonce value of the digest, changed every X mn */ protected String old_nonce = null; private long prev_date = 0; private int nonce_ttl = 600; /* 10mn by default */ /** * Get a pointer to our realm, and initialize our ipmatcher. */ protected synchronized void acquireRealm() { // Get our catalog: if ( catalog == null ) { httpd server = (httpd) ((FramedResource) getTargetResource()).getServer() ; catalog = server.getRealmsCatalog() ; } // Check that our realm name is valid: String name = getRealm() ; if ( name == null ) return ; if ((rr_realm != null) && name.equals(loaded_realm)) return ; // Load the realm and create the ipmtacher object rr_realm = catalog.loadRealm(name) ; loaded_realm = name; } /** * Check that our realm does exist. * Otherwise we are probably being initialized, and we don't authenticate * yet. * @return A boolean <strong>true</strong> if realm can be initialized. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -