You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by bu...@apache.org on 2004/07/07 10:19:20 UTC

DO NOT REPLY [Bug 29943] New: - TokenProcessor generates double tokens on fast processors

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=29943>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=29943

TokenProcessor generates double tokens on fast processors

           Summary: TokenProcessor generates double tokens on fast
                    processors
           Product: Struts
           Version: Nightly Build
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Minor
          Priority: Other
         Component: Utilities
        AssignedTo: dev@struts.apache.org
        ReportedBy: e.vanoosten@chello.nl


On really fast processors the TokenProcessor may generate the same token twice.
This happens when System.currentTimeMillis() returns the same amount multiple
times. I have seen this happen on really fast systems.

Note that it is really unlikely that the bug will occur in reality since the
same user would have to request 2 forms simultaneously.

The following patch solves the bug anyway by using a random generator.

I have made more small changes that are not directly related to this bug: 
- I did not understand why the existing implementation catches
IllegalStateException, so I removed it. Please keep the catch when I missed
something (or just to be sure).
- I did not understand why the existing implementation silently suppresses
NoSuchAlgorithmException, so I added some behaviour.
- The toHex method has been slightly improved.


	/** A random generator to prevent double tokens on really fast systems. */
	private Random randomGenerator;


	/**
	 * Generate a new transaction token, to be used for enforcing a single
	 * request for a particular transaction.
	 * 
	 * @param request The request we are processing
	 * @return the generated token
	 */
	private String generateToken(HttpServletRequest request) {
		// The following data is used for a token: 
		// - id of the session
		// - current time
		// - some random bytes, on really fast machines the same
		//   time is often returned twice or more
		//   Note that a random is used instead of a sequence number
		//   to prevent the use of another synchronisation point.
		
		HttpSession session = request.getSession();
		byte id[] = session.getId().getBytes();
		byte now[] = new Long(System.currentTimeMillis()).toString().getBytes();
		byte rnd[] = new byte[] { (byte) randomGenerator.nextInt(), (byte)
randomGenerator.nextInt() };

		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(id);
			md.update(now);
			md.update(rnd);
			return toHex(md.digest());

		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Not a valid JRE: MD5 algorithm not supported");
		}
	}

	/**
	 * Convert a byte array to a String of hexadecimal digits and return it.
	 * @param buffer The byte array to be converted
	 * @return a hex string representation of the byte array
	 */
	private static String toHex(byte buffer[]) {
		StringBuffer sb = new StringBuffer(buffer.length * 2);
		for (int i = 0; i < buffer.length; i++) {
			sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
			sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
		}
		return sb.toString();
	}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org