SpringBoot下實(shí)現(xiàn)前端驗(yàn)證碼圖片的生成和校驗(yàn),供大家參考,具體內(nèi)容如下
1.效果
點(diǎn)擊驗(yàn)證碼可以獲取新的驗(yàn)證碼
2.原理
后臺(tái)生成驗(yàn)證碼圖片,將圖片傳到前臺(tái)。
后臺(tái)在session中保存驗(yàn)證碼內(nèi)容。
前臺(tái)輸入驗(yàn)證碼后傳到后臺(tái)在后臺(tái)取出session中保存的驗(yàn)證碼進(jìn)行校驗(yàn)。
注意,驗(yàn)證碼的明文是不能傳送到前端的。前端內(nèi)容都是透明的,不安全。驗(yàn)證碼是用來(lái)防機(jī)器人并不是單單防人。如果把驗(yàn)證碼明文傳到前端很容易就會(huì)被破解。
3.圖片生成
驗(yàn)證碼生成工具類RandomValidateCodeUtil
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
|
public class RandomValidateCodeUtil { public static final String RANDOMCODEKEY= "RANDOMVALIDATECODEKEY" ; //放到session中的key private String randString = "0123456789" ; //隨機(jī)產(chǎn)生只有數(shù)字的字符串 private String //private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//隨機(jī)產(chǎn)生只有字母的字符串 //private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//隨機(jī)產(chǎn)生數(shù)字與字母組合的字符串 private int width = 95 ; // 圖片寬 private int height = 25 ; // 圖片高 private int lineSize = 40 ; // 干擾線數(shù)量 private int stringNum = 4 ; // 隨機(jī)產(chǎn)生字符數(shù)量 private static final Logger logger = LoggerFactory.getLogger(RandomValidateCodeUtil. class ); private Random random = new Random(); /** * 獲得字體 */ private Font getFont() { return new Font( "Fixedsys" , Font.CENTER_BASELINE, 18 ); } /** * 獲得顏色 */ private Color getRandColor( int fc, int bc) { if (fc > 255 ) fc = 255 ; if (bc > 255 ) bc = 255 ; int r = fc + random.nextInt(bc - fc - 16 ); int g = fc + random.nextInt(bc - fc - 14 ); int b = fc + random.nextInt(bc - fc - 18 ); return new Color(r, g, b); } /** * 生成隨機(jī)圖片 */ public void getRandcode(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); // BufferedImage類是具有緩沖區(qū)的Image類,Image類是用于描述圖像信息的類 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics(); // 產(chǎn)生Image對(duì)象的Graphics對(duì)象,改對(duì)象可以在圖像上進(jìn)行各種繪制操作 g.fillRect( 0 , 0 , width, height); //圖片大小 g.setFont( new Font( "Times New Roman" , Font.ROMAN_BASELINE, 18 )); //字體大小 g.setColor(getRandColor( 110 , 133 )); //字體顏色 // 繪制干擾線 for ( int i = 0 ; i <= lineSize; i++) { drowLine(g); } // 繪制隨機(jī)字符 String randomString = "" ; for ( int i = 1 ; i <= stringNum; i++) { randomString = drowString(g, randomString, i); } logger.info(randomString); //將生成的隨機(jī)字符串保存到session中 session.removeAttribute(RANDOMCODEKEY); session.setAttribute(RANDOMCODEKEY, randomString); g.dispose(); try { // 將內(nèi)存中的圖片通過(guò)流動(dòng)形式輸出到客戶端 ImageIO.write(image, "JPEG" , response.getOutputStream()); } catch (Exception e) { logger.error( "將內(nèi)存中的圖片通過(guò)流動(dòng)形式輸出到客戶端失敗>>>> " , e); } } /** * 繪制字符串 */ private String drowString(Graphics g, String randomString, int i) { g.setFont(getFont()); g.setColor( new Color(random.nextInt( 101 ), random.nextInt( 111 ), random .nextInt( 121 ))); String rand = String.valueOf(getRandomString(random.nextInt(randString .length()))); randomString += rand; g.translate(random.nextInt( 3 ), random.nextInt( 3 )); g.drawString(rand, 13 * i, 16 ); return randomString; } /** * 繪制干擾線 */ private void drowLine(Graphics g) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt( 13 ); int yl = random.nextInt( 15 ); g.drawLine(x, y, x + xl, y + yl); } /** * 獲取隨機(jī)的字符 */ public String getRandomString( int num) { return String.valueOf(randString.charAt(num)); } } |
在Controller調(diào)用生成驗(yàn)證碼圖片方法并將圖片傳到前端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 生成驗(yàn)證碼 */ @RequestMapping (value = "/getVerify" ) public void getVerify(HttpServletRequest request, HttpServletResponse response) { try { response.setContentType( "image/jpeg" ); //設(shè)置相應(yīng)類型,告訴瀏覽器輸出的內(nèi)容為圖片 response.setHeader( "Pragma" , "No-cache" ); //設(shè)置響應(yīng)頭信息,告訴瀏覽器不要緩存此內(nèi)容 response.setHeader( "Cache-Control" , "no-cache" ); response.setDateHeader( "Expire" , 0 ); RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil(); randomValidateCode.getRandcode(request, response); //輸出驗(yàn)證碼圖片方法 } catch (Exception e) { logger.error( "獲取驗(yàn)證碼失敗>>>> " , e); } } |
前端獲取驗(yàn)證碼圖片
html
1
2
3
4
5
6
7
8
9
10
11
12
|
< div class = "row" > < div class = "col-xs-6 pull_left" > < div class = "form-group" > < input class = "form-control" type = "tel" id = "verify_input" placeholder = "請(qǐng)輸入驗(yàn)證碼" maxlength = "4" > </ div > </ div > < div class = "col-xs-6 pull_left" > < a href = "javascript:void(0);" rel = "external nofollow" title = "點(diǎn)擊更換驗(yàn)證碼" > < img id = "imgVerify" src = "" alt = "更換驗(yàn)證碼" height = "36" width = "100%" onclick = "getVerify(this);" > </ a > </ div > </ div > |
js
1
2
3
4
|
//獲取驗(yàn)證碼 function getVerify(obj){ obj.src = httpurl + "/sys/getVerify?" +Math.random(); } |
每次點(diǎn)擊圖片重新刷新驗(yàn)證碼
界面初次加載時(shí),調(diào)用getVerify()方法即可。
4.驗(yàn)證碼驗(yàn)證
前端獲取用戶輸入的驗(yàn)證碼,傳到后臺(tái)進(jìn)行驗(yàn)證。
后臺(tái)驗(yàn)證代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/** * 忘記密碼頁(yè)面校驗(yàn)驗(yàn)證碼 */ @RequestMapping (value = "/checkVerify" , method = RequestMethod.POST, headers = "Accept=application/json" ) public boolean checkVerify( @RequestBody Map<String, Object> requestMap, HttpSession session) { try { //從session中獲取隨機(jī)數(shù) String inputStr = requestMap.get( "inputStr" ).toString(); String random = (String) session.getAttribute( "RANDOMVALIDATECODEKEY" ); if (random == null ) { return false ; } if (random.equals(inputStr)) { return true ; } else { return false ; } } catch (Exception e){ logger.error( "驗(yàn)證碼校驗(yàn)失敗" , e); return false ; } } |
后臺(tái)校驗(yàn)后,返給前端驗(yàn)證結(jié)果true或者false即可。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/colton_null/article/details/78744240