好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Java实现动态验证码生成

本文实例为大家分享了Java动态验证码生成的具体代码,供大家参考,具体内容如下

说明: 今天给大家来带来一个自动生成验证码的处理方法。验证码的出现有效减少了注入灌水以及破解密码等恶意操作,提高了系统运行的流畅性,保护了系统用户的隐私安全,具体实现方法如下:

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

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

package com.ordering.util;

 

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import java.util.Random;

 

/**

  * 验证码生成器

  * @author 诺坎普10号

  * @date 2020-2-25

  */

public class CpachaUtil {

    

     /**

     * 验证码来源

     */

     final private char [] code = {

         '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,

         'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' ,

         'k' , 'm' , 'n' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 

         'w' , 'x' , 'y' , 'z' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' ,

         'G' , 'H' , 'J' , 'K' , 'L' , 'M' , 'N' , 'P' , 'Q' , 'R' ,

         'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'

     };

     /**

     * 字体

     */

     final private String[] fontNames = new String[]{

             "黑体" , "宋体" , "Courier" , "Arial" , 

             "Verdana" , "Times" , "Tahoma" , "Georgia" };

     /**

     * 字体样式

     */

     final private int [] fontStyles = new int []{

             Font.BOLD, Font.ITALIC|Font.BOLD

     };

    

     /**

     * 验证码长度

     * 默认4个字符

     */

     private int vcodeLen = 4 ;

     /**

     * 验证码图片字体大小

     * 默认17

     */

     private int fontsize = 21 ;

     /**

     * 验证码图片宽度

     */

     private int width = (fontsize+ 1 )*vcodeLen+ 10 ;

     /**

     * 验证码图片高度

     */

     private int height = fontsize+ 12 ;

     /**

     * 干扰线条数

     * 默认3条

     */

     private int disturbline = 3 ;

    

    

     public CpachaUtil(){}

    

     /**

     * 指定验证码长度

     * @param vcodeLen 验证码长度

     */

     public CpachaUtil( int vcodeLen) {

         this .vcodeLen = vcodeLen;

         this .width = (fontsize+ 1 )*vcodeLen+ 10 ;

     }

    

     /**

     * 指定验证码长度、图片宽度、高度

     * @param vcodeLen

     * @param width

     * @param height

     */

     public CpachaUtil( int vcodeLen, int width, int height) {

         this .vcodeLen = vcodeLen;

         this .width = width;

         this .height = height;

     }

    

     /**

     * 生成验证码图片

     * @param vcode 要画的验证码

     * @param drawline 是否画干扰线

     * @return

     */

     public BufferedImage generatorVCodeImage(String vcode, boolean drawline){

         //创建验证码图片

         BufferedImage vcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

         Graphics g = vcodeImage.getGraphics();

         //填充背景色

         g.setColor( new Color( 246 , 240 , 250 ));

         g.fillRect( 0 , 0 , width, height);

         if (drawline){

             drawDisturbLine(g);

         }

         //用于生成伪随机数

         Random ran = new Random();

         //在图片上画验证码

         for ( int i = 0 ;i < vcode.length();i++){

             //设置字体

             g.setFont( new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize));

             //随机生成颜色

             g.setColor(getRandomColor());

             //画验证码

             g.drawString(vcode.charAt(i)+ "" , i*fontsize+ 10 , fontsize+ 5 );

         }

         //释放此图形的上下文以及它使用的所有系统资源

         g.dispose();

        

         return vcodeImage;

     }

     /**

     * 获得旋转字体的验证码图片

     * @param vcode

     * @param drawline 是否画干扰线

     * @return

     */

     public BufferedImage generatorRotateVCodeImage(String vcode, boolean drawline){

         //创建验证码图片

         BufferedImage rotateVcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

         Graphics2D g2d = rotateVcodeImage.createGraphics();

         //填充背景色

         g2d.setColor( new Color( 246 , 240 , 250 ));

         g2d.fillRect( 0 , 0 , width, height);

         if (drawline){

             drawDisturbLine(g2d);

         }

         //在图片上画验证码

         for ( int i = 0 ;i < vcode.length();i++){

             BufferedImage rotateImage = getRotateImage(vcode.charAt(i));

             g2d.drawImage(rotateImage, null , ( int ) ( this .height * 0.7 ) * i, 0 );

         }

         g2d.dispose();

         return rotateVcodeImage;

     }

     /**

     * 生成验证码

     * @return 验证码

     */

     public String generatorVCode(){

         int len = code.length;

         Random ran = new Random();

         StringBuffer sb = new StringBuffer();

         for ( int i = 0 ;i < vcodeLen;i++){

             int index = ran.nextInt(len);

             sb.append(code[index]);

         }

         return sb.toString();

     }

     /**

     * 为验证码图片画一些干扰线

     * @param g 

     */

     private void drawDisturbLine(Graphics g){

         Random ran = new Random();

         for ( int i = 0 ;i < disturbline;i++){

             int x1 = ran.nextInt(width);

             int y1 = ran.nextInt(height);

             int x2 = ran.nextInt(width);

             int y2 = ran.nextInt(height);

             g.setColor(getRandomColor());

             //画干扰线

             g.drawLine(x1, y1, x2, y2);

         }

     }

     /**

     * 获取一张旋转的图片

     * @param c 要画的字符

     * @return

     */

     private BufferedImage getRotateImage( char c){

         BufferedImage rotateImage = new BufferedImage(height, height, BufferedImage.TYPE_INT_ARGB);

         Graphics2D g2d = rotateImage.createGraphics();

         //设置透明度为0

         g2d.setColor( new Color( 255 , 255 , 255 , 0 ));

         g2d.fillRect( 0 , 0 , height, height);

         Random ran = new Random();

         g2d.setFont( new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize));

         g2d.setColor(getRandomColor());

         double theta = getTheta();

         //旋转图片

         g2d.rotate(theta, height/ 2 , height/ 2 );

         g2d.drawString(Character.toString(c), (height-fontsize)/ 2 , fontsize+ 5 );

         g2d.dispose();

        

         return rotateImage;

     }

     /**

     * @return 返回一个随机颜色

     */

     private Color getRandomColor(){

         Random ran = new Random();

         return new Color(ran.nextInt( 220 ), ran.nextInt( 220 ), ran.nextInt( 220 )); 

     }

     /**

     * @return 角度

     */

     private double getTheta(){

         return (( int ) (Math.random()* 1000 ) % 2 == 0 ? - 1 : 1 )*Math.random();

     }

 

     /**

     * @return 验证码字符个数

     */

     public int getVcodeLen() {

         return vcodeLen;

     }

     /**

     * 设置验证码字符个数

     * @param vcodeLen

     */

     public void setVcodeLen( int vcodeLen) {

         this .width = (fontsize+ 3 )*vcodeLen+ 10 ;

         this .vcodeLen = vcodeLen;

     }

     /**

     * @return 字体大小

     */

     public int getFontsize() {

         return fontsize;

     }

     /**

     * 设置字体大小

     * @param fontsize

     */

     public void setFontsize( int fontsize) {

         this .width = (fontsize+ 3 )*vcodeLen+ 10 ;

         this .height = fontsize+ 15 ;

         this .fontsize = fontsize;

     }

     /**

     * @return 图片宽度

     */

     public int getWidth() {

         return width;

     }

     /**

     * 设置图片宽度

     * @param width

     */

     public void setWidth( int width) {

         this .width = width;

     }

     /**

     * @return 图片高度

     */

     public int getHeight() {

         return height;

     }

     /**

     * 设置图片高度

     * @param height 

     */

     public void setHeight( int height) {

         this .height = height;

     }

     /**

     * @return 干扰线条数

     */

     public int getDisturbline() {

         return disturbline;

     }

     /**

     * 设置干扰线条数

     * @param disturbline

     */

     public void setDisturbline( int disturbline) {

         this .disturbline = disturbline;

     }

    

}

2.然后在页面端定义一个显示验证码的控件,再写一个js函数来对后台动态生成验证码方法进行调用 ,主要代码如下:

?

1

2

3

4

5

6

7

8

9

< div class = "login-center-input-text" >验证码</ div >

< img id = "cpacha-img" title = "点击切换验证码" style = "cursor:pointer;" src = "get_cpacha?vl=4&w=150&h=40&type=loginCpacha" width = "110px" height = "30px" onclick = "changeCpacha()" >

</ div >

 

< script type = "text/javascript" >

function changeCpacha(){

         $("#cpacha-img").attr("src",'get_cpacha?vl=4&w=150&h=40&type=loginCpacha&t=' + new Date().getTime());

     }

</ script >

3.控制器中代码如下:

?

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

/**

     * 本系统所有的验证码均采用此方法

     * 

     * @param vcodeLen

     * @param width

     * @param height

     * @param cpachaType:用来区别验证码的类型,传入字符串

     * @param request

     * @param response

     */

     @RequestMapping (value = "/get_cpacha" , method = RequestMethod.GET)

     public void generateCpacha( @RequestParam (name = "vl" , required = false , defaultValue = "4" ) Integer vcodeLen,

             @RequestParam (name = "w" , required = false , defaultValue = "100" ) Integer width,

             @RequestParam (name = "h" , required = false , defaultValue = "30" ) Integer height,

             @RequestParam (name = "type" , required = true , defaultValue = "loginCpacha" ) String cpachaType,

             HttpServletRequest request, HttpServletResponse response) {

         //根据页面传入的验证码长度、图片宽度以及图片长度来实例化验证码实体

         CpachaUtil cpachaUtil = new CpachaUtil(vcodeLen, width, height);

         //生成验证码

         String generatorVCode = cpachaUtil.generatorVCode();

         //把验证码存入session

         request.getSession().setAttribute(cpachaType, generatorVCode);

         //根据验证码生成相应的验证码图片

         BufferedImage generatorRotateVCodeImage = cpachaUtil.generatorRotateVCodeImage(generatorVCode, true );

         try {

             ImageIO.write(generatorRotateVCodeImage, "gif" , response.getOutputStream());

         } catch (IOException e) {

             // TODO Auto-generated catch block

             e.printStackTrace();

         }

     }

4.实现效果 如下图所示:

5.控制器验证码验证部分 如下图所示:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

//若验证码为空

if (StringUtils.isEmpty(cpacha)) {

             ret.put( "type" , "error" );

             ret.put( "msg" , "请填写验证码!" );

             return ret;

         }

         //获取保存在session中的登录验证码对象

         Object loginCpacha = request.getSession().getAttribute( "loginCpacha" );

         //若登录验证码实体对象为空

         if (loginCpacha == null ) {

             ret.put( "type" , "error" );

             ret.put( "msg" , "会话超时,请刷新页面!" );

             return ret;

         }

         //若输入的验证码转化成大写之后不等于转换成大写的session中保存的验证码

         if (!cpacha.toUpperCase().equals(loginCpacha.toString().toUpperCase())) {

             ret.put( "type" , "error" );

             ret.put( "msg" , "验证码错误!" );

             //实例化日志信息实体

             OrderingLog orderingLog = new OrderingLog( "用户名为" + user.getOuUsername() + "的用户登录时输入验证码错误!" , new Date());

             //添加日志信息

             logService.addLog(orderingLog);

             return ret;

         }

注意:

只有当你把当前系统时间传入该验证码生成工具类中,才能实现点击验证码图片,实时自动替换验证码,如下图所示:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:https://blog.csdn.net/weixin_44009447/article/details/105667939

查看更多关于Java实现动态验证码生成的详细内容...

  阅读:16次