Skip to content

Commit 14c797f

Browse files
committed
优化“如何产生一个随机的字母数字串作为 session 的唯一标识符”
1 parent e928fd5 commit 14c797f

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ stackoverflow-Java-top-qa
5656
* [什么在java中存放密码更倾向于char[]而不是String](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/why-is-cha[]-preferred-over-String-for-passwords-in-java.md)
5757
* [如何避免在JSP文件中使用Java代码](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/how-to-avoid-java-code-in-jsp-files.md)
5858
* [Java 源码里的设计模式](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/Examples_of_GoF_Design_Patterns_in_Java's_core_libraries.md)
59+
* [如何产生一个随机的字母数字串作为 session 的唯一标识符](https://github.com/giantray/stackoverflow-java-top-qa/blob/master/contents/How_to_generate_a_random_alpha-numeric_string.md)
5960

6061
> 网络
6162
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# 如何产生一个随机的字母数字串作为 session 的唯一标识符?
2+
3+
如果允许产生的随机字符串是可猜测的(随机字符串比较都短,或者使用有缺陷的随机数生成器),进而导致攻击者可能会劫持到会话的,可以使用一个相对简单随机数生成代码,如下所示:
4+
```
5+
public class RandomString {
6+
7+
private static final char[] symbols;
8+
9+
static {
10+
StringBuilder tmp = new StringBuilder();
11+
for (char ch = '0'; ch <= '9'; ++ch)
12+
tmp.append(ch);
13+
for (char ch = 'a'; ch <= 'z'; ++ch)
14+
tmp.append(ch);
15+
symbols = tmp.toString().toCharArray();
16+
}
17+
18+
private final Random random = new Random();
19+
20+
private final char[] buf;
21+
22+
public RandomString(int length) {
23+
if (length < 1)
24+
throw new IllegalArgumentException("length < 1: " + length);
25+
buf = new char[length];
26+
}
27+
28+
public String nextString() {
29+
for (int idx = 0; idx < buf.length; ++idx)
30+
buf[idx] = symbols[random.nextInt(symbols.length)];
31+
return new String(buf);
32+
}
33+
}
34+
```
35+
36+
为了安全,可以考虑使用下面这段简洁且安全的代码,不过用其作为 session 的标识符,倒显得有点大材小用了(比较耗时):
37+
```
38+
import java.security.SecureRandom;
39+
40+
public final class SessionIdentifierGenerator {
41+
private SecureRandom random = new SecureRandom();
42+
43+
public String nextSessionId() {
44+
return new BigInteger(130, random).toString(32);
45+
}
46+
}
47+
```
48+
49+
其工作原理就是,使用一个 130 位的安全的随机数生成器生成一个随机数,接着转化为 32 进制。我们知道,128 位安全随机数的生成已经是足够安全的,不过以 32 进制编码的每一个数字可编码 5 位,所以需要取大于 128 且是 5 的倍数,所以就选择了 130 位。相对于 随机 UUID 来说(在标准输出中,每个字符使用 3.4 bit,共 122 bit),每个字符使用 5 个随机的 bit 来编码的方式,显得更为简洁和高效。
50+
51+
译者注:上面两段代码,生成26位随机字符串,第一段代码每次耗时不到1ms,第二段耗时约100ms。也就是说第一段代码更快,但第二段代码更安全,但更耗时。
52+
53+
stackoverflow原链接:
54+
http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string

0 commit comments

Comments
 (0)