国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java使用google身份驗證器實現動態口令驗證的示例

java使用google身份驗證器實現動態口令驗證的示例

2020-12-16 13:18Mr_Smile2014 Java教程

本篇文章主要介紹了java使用google身份驗證器實現動態口令驗證的示例,具有一定的參考價值,有興趣的可以了解一下

最近有用戶反應我們現有的短信+郵件驗證,不安全及短信條數限制和郵件收驗證碼比較慢的問題,希望我們也能做一個類似銀行動態口令的驗證方式。經過對可行性的分析及慎重考慮,可以實現一個這樣的功能。

怎么實現呢,是自己開發一個這樣的app?這樣成本太高了,為了節約成本,我們使用互聯網使用比較多的google身份驗證器。使用它,我們只需要開發服務端就可以了。

google身份驗證器的原理是什么呢?客戶端和服務器事先協商好一個密鑰k,用于一次性密碼的生成過程,此密鑰不被任何第三方所知道。此外,客戶端和服務器各有一個計數器c,并且事先將計數值同步。進行驗證時,客戶端對密鑰和計數器的組合(k,c)使用hmac(hash-based message authentication code)算法計算一次性密碼,公式如下:

java" id="highlighter_612166">
 
?
1
 
hotp(k,c) = truncate(hmac-sha-1(k,c))

上面采用了hmac-sha-1,當然也可以使用hmac-md5等。hmac算法得出的值位數比較多,不方便用戶輸入,因
此需要截斷(truncate)成為一組不太長十進制數(例如6位)。計算完成之后客戶端計數器c計數值加1。用戶將這一組十
進制數輸入并且提交之后,服務器端同樣的計算,并且與用戶提交的數值比較,如果相同,則驗證通過,服務器端將計數值
c增加1。如果不相同,則驗證失敗。

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package com.auth.google;
 
import java.security.invalidkeyexception;
import java.security.nosuchalgorithmexception;
import java.security.securerandom;
import javax.crypto.mac;
import javax.crypto.spec.secretkeyspec;
import org.apache.commons.codec.binary.base32;
import org.apache.commons.codec.binary.base64;
 
/**
 *
 *
 * google身份驗證器,java服務端實現
 *
 * @author yangbo
 *
 * @version 創建時間:2017年8月14日 上午10:10:02
 *
 *
 */
public class googleauthenticator {
 
 // 生成的key長度( generate secret key length)
 public static final int secret_size = 10;
 
 public static final string seed = "g8gjevtbw5ovsv7avl47357438reyhreyuryetredldvks2m0qn7vxrs2im5mdancwgmcd2rvczx";
 // java實現隨機數算法
 public static final string random_number_algorithm = "sha1prng";
 // 最多可偏移的時間
 int window_size = 3; // default 3 - max 17
 
 /**
 * set the windows size. this is an integer value representing the number of
 * 30 second windows we allow the bigger the window, the more tolerant of
 * clock skew we are.
 *
 * @param s
 *  window size - must be >=1 and <=17. other values are ignored
 */
 public void setwindowsize(int s) {
 if (s >= 1 && s <= 17)
  window_size = s;
 }
 
 /**
 * generate a random secret key. this must be saved by the server and
 * associated with the users account to verify the code displayed by google
 * authenticator. the user must register this secret on their device.
 * 生成一個隨機秘鑰
 *
 * @return secret key
 */
 public static string generatesecretkey() {
 securerandom sr = null;
 try {
  sr = securerandom.getinstance(random_number_algorithm);
  sr.setseed(base64.decodebase64(seed));
  byte[] buffer = sr.generateseed(secret_size);
  base32 codec = new base32();
  byte[] bencodedkey = codec.encode(buffer);
  string encodedkey = new string(bencodedkey);
  return encodedkey;
 } catch (nosuchalgorithmexception e) {
  // should never occur... configuration error
 }
 return null;
 }
 
 /**
 * return a url that generates and displays a qr barcode. the user scans
 * this bar code with the google authenticator application on their
 * smartphone to register the auth code. they can also manually enter the
 * secret if desired
 *
 * @param user
 *  user id (e.g. fflinstone)
 * @param host
 *  host or system that the code is for (e.g. myapp.com)
 * @param secret
 *  the secret that was previously generated for this user
 * @return the url for the qr code to scan
 */
 public static string getqrbarcodeurl(string user, string host, string secret) {
 string format = "http://www.google.com/chart?chs=200x200&chld=m%%7c0&cht=qr&chl=otpauth://totp/%s@%s?secret=%s";
 return string.format(format, user, host, secret);
 }
 
 /**
 * 生成一個google身份驗證器,識別的字符串,只需要把該方法返回值生成二維碼掃描就可以了。
 *
 * @param user
 *  賬號
 * @param secret
 *  密鑰
 * @return
 */
 public static string getqrbarcode(string user, string secret) {
 string format = "otpauth://totp/%s?secret=%s";
 return string.format(format, user, secret);
 }
 
 /**
 * check the code entered by the user to see if it is valid 驗證code是否合法
 *
 * @param secret
 *  the users secret.
 * @param code
 *  the code displayed on the users device
 * @param t
 *  the time in msec (system.currenttimemillis() for example)
 * @return
 */
 public boolean check_code(string secret, long code, long timemsec) {
 base32 codec = new base32();
 byte[] decodedkey = codec.decode(secret);
 // convert unix msec time into a 30 second "window"
 // this is per the totp spec (see the rfc for details)
 long t = (timemsec / 1000l) / 30l;
 // window is used to check codes generated in the near past.
 // you can use this value to tune how far you're willing to go.
 for (int i = -window_size; i <= window_size; ++i) {
  long hash;
  try {
  hash = verify_code(decodedkey, t + i);
  } catch (exception e) {
  // yes, this is bad form - but
  // the exceptions thrown would be rare and a static
  // configuration problem
  e.printstacktrace();
  throw new runtimeexception(e.getmessage());
  // return false;
  }
  if (hash == code) {
  return true;
  }
 }
 // the validation code is invalid.
 return false;
 }
 
 private static int verify_code(byte[] key, long t) throws nosuchalgorithmexception, invalidkeyexception {
 byte[] data = new byte[8];
 long value = t;
 for (int i = 8; i-- > 0; value >>>= 8) {
  data[i] = (byte) value;
 }
 secretkeyspec signkey = new secretkeyspec(key, "hmacsha1");
 mac mac = mac.getinstance("hmacsha1");
 mac.init(signkey);
 byte[] hash = mac.dofinal(data);
 int offset = hash[20 - 1] & 0xf;
 // we're using a long because java hasn't got unsigned int.
 long truncatedhash = 0;
 for (int i = 0; i < 4; ++i) {
  truncatedhash <<= 8;
  // we are dealing with signed bytes:
  // we just keep the first byte.
  truncatedhash |= (hash[offset + i] & 0xff);
 }
 truncatedhash &= 0x7fffffff;
 truncatedhash %= 1000000;
 return (int) truncatedhash;
 }
}

測試代碼:

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.auth.google;
 
import org.junit.test;
 
/**
 *
 *
 * 身份認證測試
 *
 * @author yangbo
 *
 * @version 創建時間:2017年8月14日 上午11:09:23
 *
 *
 */
public class authtest {
 //當測試authtest時候,把gensecrettest生成的secret值賦值給它
 private static string secret="r2q3s52rnxbtftom";
 
 //@test
 public void gensecrettest() {// 生成密鑰
  secret = googleauthenticator.generatesecretkey();
 // 把這個qrcode生成二維碼,用google身份驗證器掃描二維碼就能添加成功
 string qrcode = googleauthenticator.getqrbarcode("2816661736@qq.com", secret);
 system.out.println("qrcode:" + qrcode + ",key:" + secret);
 }
 /**
 * 對app的隨機生成的code,輸入并驗證
 */
 @test
 public void verifytest() {
 long code = 807337;
 long t = system.currenttimemillis();
 googleauthenticator ga = new googleauthenticator();
 ga.setwindowsize(5);
 boolean r = ga.check_code(secret, code, t);
 system.out.println("檢查code是否正確?" + r);
 }
}

具體使用方式(ios演示):

第一步:進入iphone的appstore,在搜索框中輸入google身份驗證器,如下圖:

java使用google身份驗證器實現動態口令驗證的示例

選擇上圖中的google authenticator 并安裝。

第二步:運行下面鏈接中下載的demo中的authtest的gensecrettest方法,控制臺打印的結果如下圖:

java使用google身份驗證器實現動態口令驗證的示例

key:為app與服務端約定的秘鑰,用于雙方的認證。

qrcode:是app掃碼能夠識別的就是二維碼值,把它生成二維碼如下圖:

java使用google身份驗證器實現動態口令驗證的示例

第三步:打開google authenticator app軟件選擇掃描條形碼按扭打開相機對二維碼掃描加入賬號,如下圖:

java使用google身份驗證器實現動態口令驗證的示例

第四步:把app中的數字,在authtest的verifytest進行驗證,如下圖:

java使用google身份驗證器實現動態口令驗證的示例

通過上面給大家分享了google身份認證器服務端key的生成和它生成的隨機密碼的驗證。

上面使用的代碼已上傳到碼云,下載地址:googleauth.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/mr_smile2014/article/details/77160873

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 特级西西人体4444xxxx | 久久精品视频一区 | 亚洲一区二区三区在线 | 亚洲电影一区二区三区 | 白浆在线| 国产一区二区三区免费看 | 精品日韩一区二区三区 | 999精品视频 | 日韩免费一区二区 | 亚洲视频1区 | 久久黄色网 | 欧美精三区欧美精三区 | 91av爱爱 | 一区二区亚洲 | 国产精品18久久久 | 中文字幕国产一区 | 欧美在线免费 | 午夜伦理影院 | 亚洲精品国精品久久99热 | 亚洲第一成年人视频 | 欧美日韩一区二区视频在线观看 | 爱爱视频网站 | 亚洲精品男人的天堂 | 谁有毛片网站 | 91视频导航 | 国产欧美视频一区二区三区 | 欧美国产精品一区二区三区 | 性刺激久久久久久久久九色 | 午夜爽爽影院 | 欧美大片一区二区 | 免费在线黄色网址 | 日韩成人免费在线 | 成av人片在线观看www | 91精品国产91久久久久久吃药 | 日韩欧美精品在线 | 欧美日韩第一页 | 国产一区二区精品在线 | 午夜影晥 | 国产成人一级毛片 | 一级毛片在线播放 | 99精品免费 |