其實實現程式碼的邏輯非常簡單,真的超級超級簡單。
1、在登入頁面上login.jsp將驗證碼圖片使用標籤<img src="xxx">將繪製驗證碼圖片的url給它
2、在伺服器端就兩個servlet,一個就是用來繪製驗證碼圖片的VerifyCodeServlet,另一個就是登入時驗證驗證碼是否點寫正確或是否重複提交的LoginServlet
3、在VerifyCodeServlet中,將驗證碼的四個字母存入session中,然後在LoginServlet中,將請求中提交過來的驗證碼與session中的進行對比,如果正確,則驗證成功,並且將session中的驗證碼刪除,為什麼要刪除?保證session中的資料只能被用一次,防止重複提交資料,如果不正確,就使用request,將錯誤資訊儲存,然後請求轉發到登入頁面顯示錯誤資訊,如果發現session中的資料為null,說明重複提交了資料,也將錯誤資訊用同樣的方法返回到登入頁面。
難點就在於:VerifyCodeServlet的程式碼實現.對繪圖的程式碼不是很熟悉。
login.jsp
<body> <% String msg = (String)request.getAttribute("msg"); if(msg != null){ out.print(msg); } %> <form action="/test01/LoginServlet" method="post"> 使用者名稱:<input type="text" name="username" /> <br/> 驗證碼:<input type="text" name="verifyCode" size="5" /> <img src="/test01/VerifyCodeServlet" /> <br/> <input type="submit" value="提交"/> </form> </body>
VerifyCodeServlet.java
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //宣告驗證碼 int width = 60; int height = 30; String data = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789abcdefghijklmnpqrstuvwxyz"; //隨機字元字典,其中0,o,1,I 等難辨別的字元最好不要 Random random = new Random();//隨機類 //1 建立圖片資料快取區域(核心類) BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//建立一個彩色的圖片 //2 獲得畫板(圖片,ps圖層),繪畫物件。 Graphics g = image.getGraphics(); //3 選擇顏色,畫矩形3,4步是畫一個有內外邊框的效果 g.setColor(Color.BLACK); g.fillRect(0, 0, width, height); //4白色矩形 g.setColor(Color.WHITE); g.fillRect(1, 1, width-2, height-2); /**1 提供快取區域,為了存放4個隨機字元,以便存入session */ StringBuilder builder = new StringBuilder(); //5 隨機生成4個字元 //設定字型顏色 g.setFont(new Font("宋體", Font.BOLD&Font.ITALIC, 20)); for(int i = 0 ; i < 4 ;i ++){ //隨機顏色 g.setColor(new Color(random.nextInt(255),random.nextInt(255), random.nextInt(255))); //隨機字元 int index = random.nextInt(data.length()); String str = data.substring(index, index + 1); /**2 快取*/ builder.append(str); //寫入 g.drawString(str, (width / 6) * (i + 1) , 20); } //給圖中繪製噪音點,讓圖片不那麼好辨別 for(int j=0,n=random.nextInt(100);j<n;j++){ g.setColor(Color.RED); g.fillRect(random.nextInt(width),random.nextInt(height),1,1);//隨機噪音點 } /**3 獲得隨機資料,並儲存session*/ String tempStr = builder.toString(); request.getSession().setAttribute("sessionCacheData",tempStr); //.. 生成圖片傳送到瀏覽器 --相當於下載 ImageIO.write(image, "jpg", response.getOutputStream()); }
LoginServlet.java
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 獲得使用者輸入的驗證碼 String verifyCode = request.getParameter("verifyCode"); //2 獲得伺服器session 存放資料 ,如果沒有返回null String sessionCacheData = (String) request.getSession().getAttribute("sessionCacheData"); // *將伺服器快取session資料移除 request.getSession().removeAttribute("sessionCacheData"); // ** 判斷伺服器是否存在 if(sessionCacheData == null){ request.setAttribute("msg", "請不要重複提交"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; } //3 比較 if(! sessionCacheData.equalsIgnoreCase(verifyCode)){ //使用者輸入錯誤 // * 存放request作用域 request.setAttribute("msg", "驗證碼輸入錯誤"); // * 請求轉發 request.getRequestDispatcher("/login.jsp").forward(request, response); return; } //...... 登入操作 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
效果圖:
驗證碼錯誤時:
注意:
如果要拷貝程式碼的話,需要改就應該就是那幾處url,你的肯定跟我的不一樣,並且有些人設定的servlet的訪問路徑也不一樣,所以拷貝的話只需要拷貝關鍵程式碼即可。