From 34b7567d8f886f79b812ad17ab403491088f0a89 Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Thu, 4 Sep 2008 13:23:16 +0000 Subject: [PATCH] LMS-445 TokenGenerator with tests moved from project lims to common. SVN: 8208 --- .../cisd/common/utilities/TokenGenerator.java | 60 ++++++++++++++++ .../common/utilities/TokenGeneratorTest.java | 72 +++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java b/common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java new file mode 100644 index 00000000000..15118d7356c --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/utilities/TokenGenerator.java @@ -0,0 +1,60 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.utilities; + +import java.security.SecureRandom; +import java.util.Formatter; + +import ch.rinn.restrictions.Private; + +/** + * A generator for (pseudo-)random session tokens. It uses the lower half of a time stamp and adds a + * 128 bit pseudo-random number. Tokens are returned in hexadecimal format. + * + * @author Bernd Rinn + */ +public final class TokenGenerator +{ + @Private + static final String TIMESTAMP_FORMAT = "%1$ty%1$tm%1$td%1$tH%1$tM%1$tS%1$tL-"; + + private final SecureRandom pseudoRandomNumberGenerator = new SecureRandom(); + + /** + * @param timeStamp The time stamp (in milli-seconds since start of the epoch) to base token + * generation on. + * @return A new (pseudo-)random session token in hex format. + */ + public synchronized String getNewToken(final long timeStamp) + { + final Formatter formatter = new Formatter(); + final byte[] bytes = new byte[16]; + formatter.format(TIMESTAMP_FORMAT, timeStamp); + pseudoRandomNumberGenerator.nextBytes(bytes); + hexify(formatter, bytes); + return formatter.toString(); + } + + private static void hexify(final Formatter formatter, final byte[] bytes) + { + for (final byte b : bytes) + { + formatter.format("%02X", b); + } + } + +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java new file mode 100644 index 00000000000..b270fca9667 --- /dev/null +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/TokenGeneratorTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.utilities; + +import org.apache.commons.lang.StringUtils; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.common.utilities.TokenGenerator; + +import static org.testng.AssertJUnit.assertEquals; + +/** + * Test cases for the {@link TokenGenerator}. + * + * @author Bernd Rinn + */ +public class TokenGeneratorTest +{ + + private static final String TIMESTAMP_FORMAT = + TokenGenerator.TIMESTAMP_FORMAT.substring(0, + TokenGenerator.TIMESTAMP_FORMAT.length() - 1); + + private static boolean isHexString(String s) + { + for (int i = 0; i < s.length(); ++i) + { + if (Character.isLetterOrDigit(s.charAt(i)) == false) + { + return false; + } + } + return true; + } + + @Test + public void testTokenIsWellformed() + { + final TokenGenerator generator = new TokenGenerator(); + final long now = System.currentTimeMillis(); + final String nowFormatted = String.format(TIMESTAMP_FORMAT, now); + final String[] token = StringUtils.split(generator.getNewToken(now), '-'); + assertEquals(2, token.length); + assertEquals(nowFormatted, token[0]); + assert isHexString(token[1]) : token[1]; + } + + @Test + public void testTokensAreDifferent() + { + final TokenGenerator generator = new TokenGenerator(); + final long now = System.currentTimeMillis(); + final String[] token1 = StringUtils.split(generator.getNewToken(now), '-'); + final String[] token2 = StringUtils.split(generator.getNewToken(now), '-'); + assert token1[0].equals(token2[0]) : "'" + token1[0] + "' != '" + token2[0] + "'"; + assert token1[1].equals(token2[1]) == false : "'" + token1[1] + "' == '" + token2[1] + "'"; + } +} -- GitLab