Clover coverage report - Acegi Security System for Spring - 1.0.0-RC1
Coverage timestamp: Mon Dec 5 2005 09:05:15 EST
file stats: LOC: 137   Methods: 8
NCLOC: 70   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DigestProcessingFilterEntryPoint.java 87.5% 95.5% 100% 94.7%
coverage coverage
 1    /* Copyright 2004, 2005 Acegi Technology Pty Limited
 2    *
 3    * Licensed under the Apache License, Version 2.0 (the "License");
 4    * you may not use this file except in compliance with the License.
 5    * You may obtain a copy of the License at
 6    *
 7    * http://www.apache.org/licenses/LICENSE-2.0
 8    *
 9    * Unless required by applicable law or agreed to in writing, software
 10    * distributed under the License is distributed on an "AS IS" BASIS,
 11    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    * See the License for the specific language governing permissions and
 13    * limitations under the License.
 14    */
 15   
 16    package org.acegisecurity.ui.digestauth;
 17   
 18    import org.acegisecurity.AuthenticationException;
 19    import org.acegisecurity.intercept.web.AuthenticationEntryPoint;
 20   
 21    import org.apache.commons.codec.binary.Base64;
 22    import org.apache.commons.codec.digest.DigestUtils;
 23    import org.apache.commons.logging.Log;
 24    import org.apache.commons.logging.LogFactory;
 25   
 26    import org.springframework.beans.factory.InitializingBean;
 27   
 28    import java.io.IOException;
 29   
 30    import javax.servlet.ServletException;
 31    import javax.servlet.ServletRequest;
 32    import javax.servlet.ServletResponse;
 33    import javax.servlet.http.HttpServletResponse;
 34   
 35   
 36    /**
 37    * Used by the <code>SecurityEnforcementFilter</code> to commence
 38    * authentication via the {@link DigestProcessingFilter}.
 39    *
 40    * <p>
 41    * The nonce sent back to the user agent will be valid for the period indicated
 42    * by {@link #setNonceValiditySeconds(int)}. By default this is 300 seconds.
 43    * Shorter times should be used if replay attacks are a major concern. Larger
 44    * values can be used if performance is a greater concern. This class
 45    * correctly presents the <code>stale=true</code> header when the nonce has
 46    * expierd, so properly implemented user agents will automatically renegotiate
 47    * with a new nonce value (ie without presenting a new password dialog box to
 48    * the user).
 49    * </p>
 50    *
 51    * @author Ben Alex
 52    * @version $Id: DigestProcessingFilterEntryPoint.java,v 1.2 2005/11/17 00:56:10 benalex Exp $
 53    */
 54    public class DigestProcessingFilterEntryPoint
 55    implements AuthenticationEntryPoint, InitializingBean {
 56    //~ Static fields/initializers =============================================
 57   
 58    private static final Log logger = LogFactory.getLog(DigestProcessingFilterEntryPoint.class);
 59   
 60    //~ Instance fields ========================================================
 61   
 62    private String key;
 63    private String realmName;
 64    private int nonceValiditySeconds = 300;
 65   
 66    //~ Methods ================================================================
 67   
 68  32 public void setKey(String key) {
 69  32 this.key = key;
 70    }
 71   
 72  10 public String getKey() {
 73  10 return key;
 74    }
 75   
 76  42 public void setNonceValiditySeconds(int nonceValiditySeconds) {
 77  42 this.nonceValiditySeconds = nonceValiditySeconds;
 78    }
 79   
 80  2 public int getNonceValiditySeconds() {
 81  2 return nonceValiditySeconds;
 82    }
 83   
 84  32 public void setRealmName(String realmName) {
 85  32 this.realmName = realmName;
 86    }
 87   
 88  15 public String getRealmName() {
 89  15 return realmName;
 90    }
 91   
 92  32 public void afterPropertiesSet() throws Exception {
 93  32 if ((realmName == null) || "".equals(realmName)) {
 94  1 throw new IllegalArgumentException("realmName must be specified");
 95    }
 96   
 97  31 if ((key == null) || "".equals(key)) {
 98  1 throw new IllegalArgumentException("key must be specified");
 99    }
 100    }
 101   
 102  26 public void commence(ServletRequest request, ServletResponse response,
 103    AuthenticationException authException)
 104    throws IOException, ServletException {
 105  26 HttpServletResponse httpResponse = (HttpServletResponse) response;
 106   
 107    // compute a nonce (do not use remote IP address due to proxy farms)
 108    // format of nonce is:
 109    // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
 110  26 long expiryTime = System.currentTimeMillis()
 111    + (nonceValiditySeconds * 1000);
 112  26 String signatureValue = new String(DigestUtils.md5Hex(expiryTime + ":"
 113    + key));
 114  26 String nonceValue = expiryTime + ":" + signatureValue;
 115  26 String nonceValueBase64 = new String(Base64.encodeBase64(
 116    nonceValue.getBytes()));
 117   
 118    // qop is quality of protection, as defined by RFC 2617.
 119    // we do not use opaque due to IE violation of RFC 2617 in not
 120    // representing opaque on subsequent requests in same session.
 121  26 String authenticateHeader = "Digest realm=\"" + realmName + "\", "
 122    + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\"";
 123   
 124  26 if (authException instanceof NonceExpiredException) {
 125  2 authenticateHeader = authenticateHeader + ", stale=\"true\"";
 126    }
 127   
 128  26 if (logger.isDebugEnabled()) {
 129  0 logger.debug("WWW-Authenticate header sent to user agent: "
 130    + authenticateHeader);
 131    }
 132   
 133  26 httpResponse.addHeader("WWW-Authenticate", authenticateHeader);
 134  26 httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
 135    authException.getMessage());
 136    }
 137    }