2012-09-05 3 views
0

안녕하세요,하지만 너무 동시로 SessionID를 생성해야하는 요구 사항이 있습니다. 나는 Tomcat 7 소스 "SessionIdGenerator"에서 코드를 가져올 생각입니다. 그러나 나는 수정없이 uniqueID를 동시에 유행 시킬지 확실하지 않다.고유 ID를 동시에 생성하는 방법은 무엇입니까?

클래스 자체는 여기에 있습니다 :

공용 클래스 SessionIdGenerator {

private Logger logger = LoggerFactory.getLogger(); 



/** 
* Queue of random number generator objects to be used when creating session 
* identifiers. If the queue is empty when a random number generator is 
* required, a new random number generator object is created. This is 
* designed this way since random number generators use a sync to make them 
* thread-safe and the sync makes using a a single object slow(er). 
*/ 
private Queue<SecureRandom> randoms = new ConcurrentLinkedQueue<SecureRandom>(); 


/** 
* The Java class name of the secure random number generator class to be 
* used when generating session identifiers. The random number generator 
* class must be self-seeding and have a zero-argument constructor. If not 
* specified, an instance of {@link SecureRandom} will be generated. 
*/ 
private String secureRandomClass = null; 


/** 
* The name of the algorithm to use to create instances of 
* {@link SecureRandom} which are used to generate session IDs. If no 
* algorithm is specified, SHA1PRNG is used. To use the platform default 
* (which may be SHA1PRNG), specify the empty string. If an invalid 
* algorithm and/or provider is specified the {@link SecureRandom} instances 
* will be created using the defaults. If that fails, the {@link 
* SecureRandom} instances will be created using platform defaults. 
*/ 
private String secureRandomAlgorithm = "SHA1PRNG"; 


/** 
* The name of the provider to use to create instances of 
* {@link SecureRandom} which are used to generate session IDs. If 
* no algorithm is specified the of SHA1PRNG default is used. If an invalid 
* algorithm and/or provider is specified the {@link SecureRandom} instances 
* will be created using the defaults. If that fails, the {@link 
* SecureRandom} instances will be created using platform defaults. 
*/ 
private String secureRandomProvider = null; 


/** Node identifier when in a cluster. Defaults to the empty string. */ 
private String jvmRoute = ""; 


/** Number of bytes in a session ID. Defaults to 16. */ 
private int sessionIdLength = 16; 


/** 
* Specify a non-default @{link {@link SecureRandom} implementation to use. 
* 
* @param secureRandomClass The fully-qualified class name 
*/ 
public void setSecureRandomClass(String secureRandomClass) { 
    this.secureRandomClass = secureRandomClass; 
} 


/** 
* Specify a non-default algorithm to use to generate random numbers. 
* 
* @param secureRandomAlgorithm The name of the algorithm 
*/ 
public void setSecureRandomAlgorithm(String secureRandomAlgorithm) { 
    this.secureRandomAlgorithm = secureRandomAlgorithm; 
} 


/** 
* Specify a non-default provider to use to generate random numbers. 
* 
* @param secureRandomProvider The name of the provider 
*/ 
public void setSecureRandomProvider(String secureRandomProvider) { 
    this.secureRandomProvider = secureRandomProvider; 
} 


/** 
* Specify the node identifier associated with this node which will be 
* included in the generated session ID. 
* 
* @param jvmRoute The node identifier 
*/ 
public void setJvmRoute(String jvmRoute) { 
    this.jvmRoute = jvmRoute; 
} 


/** 
* Specify the number of bytes for a session ID 
* 
* @param sessionIdLength Number of bytes 
*/ 
public void setSessionIdLength(int sessionIdLength) { 
    this.sessionIdLength = sessionIdLength; 
} 


/** 
* Generate and return a new session identifier. 
*/ 
public String generateSessionId() { 

    byte random[] = new byte[16]; 

    // Render the result as a String of hexadecimal digits 
    StringBuilder buffer = new StringBuilder(); 

    int resultLenBytes = 0; 

    while (resultLenBytes < sessionIdLength) { 
     getRandomBytes(random); 
     for (int j = 0; 
     j < random.length && resultLenBytes < sessionIdLength; 
     j++) { 
      byte b1 = (byte) ((random[j] & 0xf0) >> 4); 
      byte b2 = (byte) (random[j] & 0x0f); 
      if (b1 < 10) 
       buffer.append((char) ('0' + b1)); 
      else 
       buffer.append((char) ('A' + (b1 - 10))); 
      if (b2 < 10) 
       buffer.append((char) ('0' + b2)); 
      else 
       buffer.append((char) ('A' + (b2 - 10))); 
      resultLenBytes++; 
     } 
    } 

    if (jvmRoute != null && jvmRoute.length() > 0) { 
     buffer.append('.').append(jvmRoute); 
    } 

    return buffer.toString(); 
} 


private void getRandomBytes(byte bytes[]) { 

    SecureRandom random = randoms.poll(); 
    if (random == null) { 
     random = createSecureRandom(); 
    } 
    random.nextBytes(bytes); 
    randoms.add(random); 
} 


/** 
* Create a new random number generator instance we should use for 
* generating session identifiers. 
*/ 
private SecureRandom createSecureRandom() { 

    SecureRandom result = null; 

    long t1 = System.currentTimeMillis(); 
    if (secureRandomClass != null) { 
     try { 
      // Construct and seed a new random number generator 
      Class<?> clazz = Class.forName(secureRandomClass); 
      result = (SecureRandom) clazz.newInstance(); 
     } catch (Exception e) { 
      logger.debug("exception:"+e); 
     } 
    } 

    if (result == null) { 
     // No secureRandomClass or creation failed. Use SecureRandom. 
     try { 
      if (secureRandomProvider != null && 
        secureRandomProvider.length() > 0) { 
       result = SecureRandom.getInstance(secureRandomAlgorithm, 
         secureRandomProvider); 
      } else if (secureRandomAlgorithm != null && 
        secureRandomAlgorithm.length() > 0) { 
       result = SecureRandom.getInstance(secureRandomAlgorithm); 
      } 
     } catch (NoSuchAlgorithmException e) { 
      logger.debug("exception:"+e); 
     } catch (NoSuchProviderException e) { 
      logger.debug("exception:"+e); 
     } 
    } 

    if (result == null) { 
     // Invalid provider/algorithm 
     try { 
      result = SecureRandom.getInstance("SHA1PRNG"); 
     } catch (NoSuchAlgorithmException e) { 
      logger.debug("exception:"+e); 
     } 
    } 

    if (result == null) { 

     // Nothing works - use platform default 
     result = new SecureRandom(); 
    } 

    // Force seeding to take place 
    result.nextInt(); 

    long t2=System.currentTimeMillis(); 
    if((t2-t1) > 100) 
     logger.debug("sessionIdGenerator algorithm:"+result.getAlgorithm()+"time taken:" +Long.valueOf(t2-t1)); 
    return result; 
} 

}

+0

질문에 해당 코드가 모두 필요합니까? – RNJ

+0

AtomicLong.getAndIncrement()를 사용할 수없는 이유가 있습니까? –

답변

2

내가 대신 java.util.UUID.randomUUID()을 사용하십시오. 아주 간단하고 독창성을 보장합니다.

+4

중요하지는 않지만'java.util.UUID.randomUUID()'는 유일성을 보장하지 않습니다. 충돌은 거의 없을 것입니다. – jarnbjo

관련 문제