一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

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

服務(wù)器之家 - 編程語言 - Java教程 - Java中SSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法

Java中SSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法

2020-08-10 19:09Lovnx Java教程

這篇文章主要介紹了 SSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

 先給大家展示下效果圖:

Java中SSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法

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
import java.util.Random;
import java.awt.image.BufferedImage;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
/**
 * 驗證碼生成器類,可生成數(shù)字、大寫、小寫字母及三者混合類型的驗證碼。 支持自定義驗證碼字符數(shù)量; 支持自定義驗證碼圖片的大小; 支持自定義需排除的特殊字符;
 * 支持自定義干擾線的數(shù)量; 支持自定義驗證碼圖文顏色
 */
public class ValidateCode {
 /**
  * 驗證碼類型為僅數(shù)字 0~9
  */
 public static final int TYPE_NUM_ONLY = 0;
 /**
  * 驗證碼類型為僅字母,即大寫、小寫字母混合
  */
 public static final int TYPE_LETTER_ONLY = 1;
 /**
  * 驗證碼類型為數(shù)字、大寫字母、小寫字母混合
  */
 public static final int TYPE_ALL_MIXED = 2;
 /**
  * 驗證碼類型為數(shù)字、大寫字母混合
  */
 public static final int TYPE_NUM_UPPER = 3;
 /**
  * 驗證碼類型為數(shù)字、小寫字母混合
  */
 public static final int TYPE_NUM_LOWER = 4;
 /**
  * 驗證碼類型為僅大寫字母
  */
 public static final int TYPE_UPPER_ONLY = 5;
 /**
  * 驗證碼類型為僅小寫字母
  */
 public static final int TYPE_LOWER_ONLY = 6;
 private ValidateCode() {
 }
 /**
  * 生成驗證碼字符串
  *
  * @param type
  *   驗證碼類型,參見本類的靜態(tài)屬性
  * @param length
  *   驗證碼長度,大于0的整數(shù)
  * @param exChars
  *   需排除的特殊字符(僅對數(shù)字、字母混合型驗證碼有效,無需排除則為null)
  * @return 驗證碼字符串
  */
 public static String generateTextCode(int type, int length, String exChars) {
  if (length <= 0)
   return "";
  StringBuffer code = new StringBuffer();
  int i = 0;
  Random r = new Random();
  switch (type) {
  // 僅數(shù)字
  case TYPE_NUM_ONLY:
   while (i < length) {
    int t = r.nextInt(10);
    if (exChars == null || exChars.indexOf(t + "") < 0) {// 排除特殊字符
     code.append(t);
     i++;
    }
   }
   break;
  // 僅字母(即大寫字母、小寫字母混合)
  case TYPE_LETTER_ONLY:
   while (i < length) {
    int t = r.nextInt(123);
    if ((t >= 97 || (t >= 65 && t <= 90)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
     code.append((char) t);
     i++;
    }
   }
   break;
  // 數(shù)字、大寫字母、小寫字母混合
  case TYPE_ALL_MIXED:
   while (i < length) {
    int t = r.nextInt(123);
    if ((t >= 97 || (t >= 65 && t <= 90) || (t >= 48 && t <= 57))
      && (exChars == null || exChars.indexOf((char) t) < 0)) {
     code.append((char) t);
     i++;
    }
   }
   break;
  // 數(shù)字、大寫字母混合
  case TYPE_NUM_UPPER:
   while (i < length) {
    int t = r.nextInt(91);
    if ((t >= 65 || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
     code.append((char) t);
     i++;
    }
   }
   break;
  // 數(shù)字、小寫字母混合
  case TYPE_NUM_LOWER:
   while (i < length) {
    int t = r.nextInt(123);
    if ((t >= 97 || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {
     code.append((char) t);
     i++;
    }
   }
   break;
  // 僅大寫字母
  case TYPE_UPPER_ONLY:
   while (i < length) {
    int t = r.nextInt(91);
    if ((t >= 65) && (exChars == null || exChars.indexOf((char) t) < 0)) {
     code.append((char) t);
     i++;
    }
   }
   break;
  // 僅小寫字母
  case TYPE_LOWER_ONLY:
   while (i < length) {
    int t = r.nextInt(123);
    if ((t >= 97) && (exChars == null || exChars.indexOf((char) t) < 0)) {
     code.append((char) t);
     i++;
    }
   }
   break;
  }
  return code.toString();
 }
 /**
  * 已有驗證碼,生成驗證碼圖片
  *
  * @param textCode
  *   文本驗證碼
  * @param width
  *   圖片寬度
  * @param height
  *   圖片高度
  * @param interLine
  *   圖片中干擾線的條數(shù)
  * @param randomLocation
  *   每個字符的高低位置是否隨機
  * @param backColor
  *   圖片顏色,若為null,則采用隨機顏色
  * @param foreColor
  *   字體顏色,若為null,則采用隨機顏色
  * @param lineColor
  *   干擾線顏色,若為null,則采用隨機顏色
  * @return 圖片緩存對象
  */
 public static BufferedImage generateImageCode(String textCode, int width, int height, int interLine,
   boolean randomLocation, Color backColor, Color foreColor, Color lineColor) {
  BufferedImage bim = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  Graphics g = bim.getGraphics();
  // 畫背景圖
  g.setColor(backColor == null ? getRandomColor() : backColor);
  g.fillRect(0, 0, width, height);
  // 畫干擾線
  Random r = new Random();
  if (interLine > 0) {
   int x = 0, y = 0, x1 = width, y1 = 0;
   for (int i = 0; i < interLine; i++) {
    g.setColor(lineColor == null ? getRandomColor() : lineColor);
    y = r.nextInt(height);
    y1 = r.nextInt(height);
    g.drawLine(x, y, x1, y1);
   }
  }
  // 寫驗證碼
  // g.setColor(getRandomColor());
  // g.setColor(isSimpleColor?Color.BLACK:Color.WHITE);
  // 字體大小為圖片高度的80%
  int fsize = (int) (height * 0.8);
  int fx = height - fsize;
  int fy = fsize;
  g.setFont(new Font("Default", Font.PLAIN, fsize));
  // 寫驗證碼字符
  for (int i = 0; i < textCode.length(); i++) {
   fy = randomLocation ? (int) ((Math.random() * 0.3 + 0.6) * height) : fy;// 每個字符高低是否隨機
   g.setColor(foreColor == null ? getRandomColor() : foreColor);
   g.drawString(textCode.charAt(i) + "", fx, fy);
   fx += fsize * 0.9;
  }
  g.dispose();
  return bim;
 }
 /**
  * 生成圖片驗證碼
  *
  * @param type
  *   驗證碼類型,參見本類的靜態(tài)屬性
  * @param length
  *   驗證碼字符長度,大于0的整數(shù)
  * @param exChars
  *   需排除的特殊字符
  * @param width
  *   圖片寬度
  * @param height
  *   圖片高度
  * @param interLine
  *   圖片中干擾線的條數(shù)
  * @param randomLocation
  *   每個字符的高低位置是否隨機
  * @param backColor
  *   圖片顏色,若為null,則采用隨機顏色
  * @param foreColor
  *   字體顏色,若為null,則采用隨機顏色
  * @param lineColor
  *   干擾線顏色,若為null,則采用隨機顏色
  * @return 圖片緩存對象
  */
 public static BufferedImage generateImageCode(int type, int length, String exChars, int width, int height,
   int interLine, boolean randomLocation, Color backColor, Color foreColor, Color lineColor) {
  String textCode = generateTextCode(type, length, exChars);
  BufferedImage bim = generateImageCode(textCode, width, height, interLine, randomLocation, backColor, foreColor,
    lineColor);
  return bim;
 }
 /**
  * 產(chǎn)生隨機顏色
  *
  * @return
  */
 private static Color getRandomColor() {
  Random r = new Random();
  Color c = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
  return c;
 }
}

2、Controller

?
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
/**
 * 生成驗證碼
 * @param request
 * @param response
 * @throws IOException
 * @ValidateCode.generateTextCode(驗證碼字符類型,驗證碼長度,需排除的特殊字符)
 * @ValidateCode.generateImageCode(文本驗證碼,圖片寬度,圖片高度,干擾線的條數(shù),字符的高低位置是否隨機,圖片顏色,字體顏色,干擾線顏色)
 */
@RequestMapping(value = "validateCode")
public void validateCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
 response.setHeader("Cache-Control", "no-cache");
 String verifyCode = ValidateCode.generateTextCode(ValidateCode.TYPE_NUM_LOWER, 4, null);
 request.getSession().setAttribute("validateCode", verifyCode);
 response.setContentType("image/jpeg");
 BufferedImage bim = ValidateCode.generateImageCode(verifyCode, 90, 30, 5, true, Color.WHITE, Color.BLUE, null);
 ImageIO.write(bim, "JPEG", response.getOutputStream());
}
/**
 * 登錄請求
 * @param
 */
@RequestMapping(value = "login", method = RequestMethod.POST, produces = "text/html; charset=utf-8")
public String login(HttpServletRequest request, HttpServletResponse response, UserEntity user) {
 //首先進行驗證碼驗證
 Session session = SecurityUtils.getSubject().getSession();
 String code = (String) session.getAttribute("validateCode");
 String submitCode = WebUtils.getCleanParam(request, "validateCode");
 if (StringUtils.isEmpty(submitCode) || !StringUtils.equals(code,submitCode.toLowerCase())) {
  request.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100000);
  request.setAttribute("LOGIN_ERROR_MESSAGE", LoginConstant.LOGIN_ERROR_MESSAGE_VALIDATECODE);
  return "login";
 }
 // 想要得到 SecurityUtils.getSubject() 的對象..訪問地址必須跟shiro的攔截地址內(nèi).不然后會報空指針
 Subject sub = SecurityUtils.getSubject();
 // 用戶輸入的賬號和密碼,,存到UsernamePasswordToken對象中..然后由shiro內(nèi)部認證對比,
 // 認證執(zhí)行者交由ShiroDbRealm中doGetAuthenticationInfo處理
 // 當以上認證成功后會向下執(zhí)行,認證失敗會拋出異常
 UsernamePasswordToken token = new UsernamePasswordToken(user.getAccountName(), user.getPassWord());
 try {
  sub.login(token);
 } catch (LockedAccountException lae) {
  token.clear();
  request.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100002);
  request.setAttribute("LOGIN_ERROR_MESSAGE", LoginConstant.LOGIN_ERROR_MESSAGE_SYSTEMERROR);
  return "login";
 } catch (ExcessiveAttemptsException e) {
  token.clear();
  request.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100003);
  request.setAttribute("LOGIN_ERROR_MESSAGE","賬號:" + user.getUserName() + LoginConstant.LOGIN_ERROR_MESSAGE_MAXERROR);
  return "login";
 } catch (AuthenticationException e) {
  token.clear();
  request.setAttribute("LOGIN_ERROR_CODE", LoginConstant.LOGIN_ERROR_CODE_100001);
  request.setAttribute("LOGIN_ERROR_MESSAGE", LoginConstant.LOGIN_ERROR_MESSAGE_USERERROR);
  return "login";
 }
 return "redirect:/index.shtml";
}

注意:

登錄方法里面一些參數(shù)的定義:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface LoginConstant
{
 String LOGIN_ERROR_CODE_100000 = "100000";
 String LOGIN_ERROR_MESSAGE_VALIDATECODE = "驗證碼輸入錯誤,請重新輸入!";
 String LOGIN_ERROR_CODE_100001 = "100001";
 String LOGIN_ERROR_MESSAGE_USERERROR = "賬號或密碼錯誤,請重新輸入!";
 String LOGIN_ERROR_CODE_100002 = "100002";
 String LOGIN_ERROR_MESSAGE_SYSTEMERROR = "用戶已經(jīng)被鎖定不能登錄,請與管理員聯(lián)系!";
 String LOGIN_ERROR_CODE_100003 = "100003";
 String LOGIN_ERROR_MESSAGE_MAXERROR = "登錄失敗次數(shù)過多,鎖定10分鐘!";
 String LOGIN_ERROR_CODE_100004 = "100004";
 String LOGIN_ERROR_MESSAGE_FORCELOGOUT = "您已經(jīng)被管理員強制退出,請重新登錄";
}

3、登錄jsp(重要代碼)

路徑信息:

?
1
2
3
4
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>

js:用于更換驗證碼圖片

?
1
2
3
4
5
<script>
 function reloadValidateCode(){
  $("#validateCodeImg").attr("src","<%=basePath%>/validateCode.shtml?data=" + new Date() + Math.floor(Math.random()*24));
 }
</script>

登錄表單里面的標簽:

?
1
<img id="validateCodeImg" src="<%=basePath%>/validateCode.shtml" />&nbsp;&nbsp;<a href="#" rel="external nofollow" onclick="javascript:reloadValidateCode();">看不清?</a>

4、Shiro匿名訪問配置(不配置無法生成驗證碼圖片)

?
1
2
3
4
5
6
7
8
<!--自定義filterChainDefinitionMap -->
 <bean id="chainDefinitionSectionMetaSource" class="com.collection.shiro.ChainDefinitionSectionMetaSource">
  <property name="filterChainDefinitions">
   <value>
    /validateCode.shtml = anon//添加這行
   </value>
  </property>
 </bean>

以上所述是小編給大家介紹的JavaSSM+Shiro系統(tǒng)登錄驗證碼的實現(xiàn)方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對服務(wù)器之家網(wǎng)站的支持!

原文鏈接:http://blog.csdn.net/rickiyeat/article/details/55050440

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 四虎影院2019| 日韩欧美亚洲国产高清在线 | chinese野外gay军人 | 国产成人综合亚洲亚洲欧美 | 男人天堂资源网 | 男老头澡堂gay老头456 | 国产美女久久精品香蕉69 | 色老大在线 | 1024国产看片在线观看 | 欧美精选欧美极品 | 美女把腿开让我 | 艾秋麻豆果冻传媒老狼仙踪林 | 欧美5g影院 | 午夜影院一区二区三区 | 成功精品影院 | 第一次做m被调教经历 | 国产亚洲精品久久yy5099 | 亚洲激情一区 | 催眠 迷j系列小说 | 日韩精品成人 | 思思久久精品在热线热 | 亚洲国产成人久久综合一区77 | 啪啪免费入口网站 | 亚洲欧美另类在线观看 | 久久夜色噜噜噜亚洲AV0000 | 成人观看免费观看视频 | 国产3级在线 | 午夜一级视频 | 羞羞答答免费人成黄页在线观看国产 | 天天摸天天碰色综合网 | 日韩精品中文字幕久久 | 欧美日韩一级视频 | 亚洲天堂成人在线观看 | 非洲黑女人性xxxx | 久久九九久精品国产尤物 | 亚裔aⅴ艳星katsuni | 国产精品制服丝袜白丝www | 国产精品久久久久久搜索 | 99久女女精品视频在线观看 | 久久亚洲网站 | 亚洲同性男男gay1069 |