Struts2中驗證碼的生成和使用

jopen 10年前發布 | 51K 次閱讀 Struts2 Web框架

第一步生產字符串:

package com.yancode.demo;


import java.util.Arrays;


/
 
一步一步來,要生成驗證碼圖片,首先要有驗證碼,然后才能在畫在圖片上。為了能夠靈活控制驗證碼,
  特別編寫了SecurityCode類,它向外提供隨機字符串。并且可以控制字符串的長度和難度。
 
SecurityCode類中提供的驗證碼分三個難度,易(全數字)、中(數字+小寫英文)、難(數字+大小寫英文)。
  難度使用枚舉SecurityCodeLevle表示,避免使用1、2、3這樣沒有明確意義的數字來區分。


  同時,還控制了能否出現重復的字符。為了能夠方便使用,方法設計為static。
 
*/
public class SecurityCode {
/**

  • 驗證碼難度級別,Simple只包含數字,Medium包含數字和小寫英文,Hard包含數字和大小寫英文
    /
    public enum SecurityCodeLevel {Simple,Medium,Hard};
        
    /**
     
    產生默認驗證碼,4位中等難度
          @return  String 驗證碼
     
    /
    public static String getSecurityCode(){
    return getSecurityCode(4,SecurityCodeLevel.Medium,false);
    }
       
       /
          產生長度和難度任意的驗證碼
         
    @param length  長度
          @param level   難度級別
         
    @param isCanRepeat  是否能夠出現重復的字符,如果為true,則可能出現 5578這樣包含兩個5,如果為false,則不可能出現這種情況
          @return  String 驗證碼
         
    /
        public static String getSecurityCode(int length,SecurityCodeLevel level,boolean isCanRepeat){
            
           //隨機抽取len個字符
            int len=length;
            
           //字符集合(除去易混淆的數字0、數字1、字母l、字母o、字母O)
           char[] codes={'1','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','I','J','K','L',
                         'M','N','P','Q','R','S','T','U','V',
                         'W','X','Y','Z'};
            
            //根據不同的難度截取字符數組
            if(level==SecurityCodeLevel.Simple){
                codes=Arrays.copyOfRange(codes, 0,9);
            }else if(level==SecurityCodeLevel.Medium){
                codes=Arrays.copyOfRange(codes, 0,33);
            }
            
            //字符集合長度
            int n=codes.length;
            //拋出運行時異常,這里的len為4
            if(len>n&&isCanRepeat==false){
                throw new RuntimeException(
                        String.format("調用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出現異常," +
                                       "當isCanRepeat為%3$s時,傳入參數%1$s不能大于%4$s",
                                       len,level,isCanRepeat,n));
            }
            
                //存放抽取出來的字符
           char[] result=new char[len];
            
            //判斷能否出現重復的字符
            if(isCanRepeat){
                for(int i=0;i<result.length;i++){
                    //索引 0 and n-1
                   int r=(int)(Math.random()n);
                
                    //將result中的第i個元素設置為codes[r]存放的數值
                    result[i]=codes[r];
                }
            }else{
                for(int i=0;i<result.length;i++){
                    //索引 0 and n-1
                    int r=(int)(Math.random()
    n);
                    
                   //將result中的第i個元素設置為codes[r]存放的數值
                   result[i]=codes[r];
                   
                    //必須確保不會再次抽取到那個字符,因為所有抽取的字符必須不相同。
                    //因此,這里用數組中的最后一個字符改寫codes[r],并將n減1
                    codes[r]=codes[n-1];
                    n--;
                }
            }
            
            return String.valueOf(result);
        }
    }</span></p>



    第二步,繪制圖片

    package com.yancode.demo;


    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.Random;


    import javax.imageio.ImageIO;




    / 第一步已經完成,有了上面SecurityCode類提供的驗證碼,就應該考慮怎么在圖片上寫字符串了。
     
    在Java中操作圖片,需要使用BufferedImage類,它代表內存中的圖片。
      寫字符串,就需要從圖片BufferedImage上得到繪圖圖面Graphics,然后在圖面上drawString。


         為了使驗證碼有一定的干擾性,也繪制了一些噪點。調用Graphics類的drawRect繪制1
    1大小的方塊就可以了。


         特別說明一下,由于后面要與Strtus2結合使用,
         而在Struts2中向前臺返回圖片數據使用的是數據流的形式。所以提供了從圖片向流的轉換方法
         */
    public class SecurityImage {
    /

      生成驗證碼圖片
     
    @param securityCode   驗證碼字符
      @return  BufferedImage  圖片
     
    /
    public static BufferedImage createImage(String securityCode){
    //驗證碼長度
    int codeLength=securityCode.length();
    //字體大小
       int fSize = 15;
       int fWidth = fSize + 1;
       //圖片寬度
       int width = codeLength fWidth + 6 ;
       //圖片高度
        int height = fSize
    2  -5;
             
        //圖片
        BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g=image.createGraphics();
             
        //設置背景色
        g.setColor(Color.WHITE);
        //填充背景,用白色填充
        g.fillRect(0, 0, width, height);
             
        //設置邊框顏色
        g.setColor(Color.LIGHT_GRAY);
        //邊框字體樣式
        g.setFont(new Font("Arial", Font.BOLD, height-2));
        //繪制邊框
        g.drawRect(0, 0, width - 1, height -1);
             
             
         //繪制噪點
         Random rand = new Random();
         //設置噪點顏色
         //g.setColor(Color.LIGHT_GRAY);
         for(int i = 0;i < codeLength 7;i++){
                 int x = rand.nextInt(width);
                 int y = rand.nextInt(height);
                 g.setColor(new Color(rand.nextInt(255),
            rand.nextInt(255),rand.nextInt(255)));
                //繪制1
    1大小的矩形
                 g.drawRect(x, y, 1, 1);
                 //g.setColor(Color.LIGHT_GRAY);
             }
             
            //繪制驗證碼
             int codeY = height - 10;  
            //設置字體顏色和樣式
            //g.setColor(new Color(19,148,246));
            g.setFont(new Font("Georgia", Font.BOLD, fSize+2));
            for(int i = 0; i < codeLength;i++){
            g.setColor(new Color(rand.nextInt(255),
            rand.nextInt(255),rand.nextInt(255)));
            g.drawString(String.valueOf(securityCode.charAt(i)),
            i 16 + 5, codeY);
             
             }
             //關閉資源
            g.dispose();
             
            return image;
         }
         
    /**
     
    返回驗證碼圖片的流格式
      @param securityCode  驗證碼
     
    @return ByteArrayInputStream 圖片流
     /
    public static ByteArrayInputStream getImageAsInputStream(String securityCode){
             BufferedImage image = createImage(securityCode);
             return convertImageToStream(image);
             }
    /**
     
    將BufferedImage轉換成ByteArrayInputStream
      @param image  圖片
     
    @return ByteArrayInputStream 流
     /
    private static ByteArrayInputStream convertImageToStream(BufferedImage image){
    ByteArrayInputStream inputStream = null;
       ByteArrayOutputStream bos = new ByteArrayOutputStream();
       byte [] bimage=null;
       try {
    ImageIO.write(image, "jpeg", bos);
    bimage=bos.toByteArray();
    inputStream = new ByteArrayInputStream(bimage);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
       //JPEGImageEncoder
       /
    JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(bos);
       try {
                jpeg.encode(image);
                byte[] bts = bos.toByteArray();
                inputStream = new ByteArrayInputStream(bts);
            } catch (ImageFormatException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return inputStream;*/
       //返回輸入流
    return inputStream;
        }

    }
    </span></p>



    第三步,生成驗證碼的action

    package com.yancode.demo;


    import java.io.ByteArrayInputStream;
    import java.util.Map;


    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionSupport;


    public class SecurityCodeImageAction extends ActionSupport {


    //圖片流
    private ByteArrayInputStream imageStream;
    private String timestamp;//得到時間戳
    public ByteArrayInputStream getImageStream() {
    return imageStream;
    }


    public void setImageStream(ByteArrayInputStream imageStream) {
    this.imageStream = imageStream;

    }


    public String getTimestamp() {
    return timestamp;
    }


    public void setTimestamp(String timestamp) {
    this.timestamp = timestamp;
    //System.out.println("時間戳timestamp:"+this.timestamp);
    }


    @Override
    public String execute() throws Exception {
    // TODO Auto-generated method stub
    //如果開啟Hard模式,可以不區分大小寫
    //String securityCode = SecurityCode.getSecurityCode(4,SecurityCodeLevel.Hard, false).toLowerCase();
           
    //獲取默認難度和長度的驗證碼
    String securityCode = SecurityCode.getSecurityCode();
    imageStream = SecurityImage.getImageAsInputStream(securityCode);
    System.out.println("code="+securityCode);
        //放入session中
    Map session=ActionContext.getContext().getSession();
    session.put("SESSION_SECURITY_CODE", securityCode);
    return SUCCESS;
    }


    }



    第四步,在struts.xml文件中配置驗證碼的action

    <!--驗證碼的action  -->
         <action name="SecurityCodeImageAction" 
             class="com.yancode.demo.SecurityCodeImageAction">
             <result name="success" type="stream">
             <param name="contentType">image/jpeg</param>
             <param name="inputName">imageStream</param>
             <param name="bufferSize">2048</param>
             </result>
          </action>

     

     

     

     

     

    第五步,在jsp中使用生成的驗證碼

    <script type="text/javascript">

       window.onload=function(){
     
       document.getElementById("img").onclick=function(){
       this.src="SecurityCodeImageAction?timestamp="+new Date().getTime();
       
        };
        
    };
    </script>




    <td>驗證碼:</td>
           <td>
           <input type="text" name="securityCode"/>
           <img src="SecurityCodeImageAction" id="img"  style="cursor:hand;" alt="看不清,換一張"/>
           <span style="color:red;" id="simg">
           <s:property value="#request.error2"></s:property>
           </span>
           <!-- <a href="javascript:;" onclick="document.getElementById('img').
    src='checkcode?'+new Date().getTime();"><span style="font-size:12px;">看不清,換一張</span></a> -->
           </td>


    注意,生成驗證碼的時候使用了時間戳,目的是為了,區別不同的提交,生產不同驗證碼

    來自:http://blog.csdn.net/j903829182/article/details/36695697
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!