zoukankan      html  css  js  c++  java
  • SpringBoot实战项目(十三)--登录功能之页面构建及验证码实现

    最终实现效果---

     杂七杂八做了不少小项目,感觉过段时间就忘,这直接就记录下来吧!

    前端什么的也只能基本看懂,注重后端开发就行

    (css,js静态资源放网盘了)

    链接:https://pan.baidu.com/s/1mOKQ9mKKJEkZn9dvmZ0GCQ
    提取码:urhv

    首先页面构建

      1 <!DOCTYPE html>
      2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
      3 <head>
      4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      5   <title>SSM框架后台管理员登录</title>
      6   <meta name="description" content="particles.js is a lightweight JavaScript library for creating particles.">
      7   <meta name="author" content="Vincent Garreau">
      8   <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
      9   <link rel="stylesheet" media="screen" th:href="@{/xadmin/login/css/style.css}">
     10   <link rel="stylesheet" type="text/css" th:href="@{/xadmin/login/css/reset.css}">
     11 <body>
     12 
     13 <div id="particles-js">
     14         <div class="login" style="display: block;">
     15             <div class="login-top">
     16                 登录
     17             </div>
     18             <div class="login-center clearfix">
     19                 <div class="login-center-img"><img th:src="@{/xadmin/login/images/name.png}"></div>
     20                 <div class="login-center-input">
     21                     <input type="text" name="userName" id="username" value="" placeholder="请输入您的用户名" onfocus="this.placeholder=&#39;&#39;" onblur="this.placeholder=&#39;请输入您的用户名&#39;">
     22                     <div class="login-center-input-text">用户名</div>
     23                 </div>
     24             </div>
     25             <div class="login-center clearfix">
     26                 <div class="login-center-img"><img th:src="@{/xadmin/login/images/password.png}"></div>
     27                 <div class="login-center-input">
     28                     <input type="password" name="passWord" id="password" value="" placeholder="请输入您的密码" onfocus="this.placeholder=&#39;&#39;" onblur="this.placeholder=&#39;请输入您的密码&#39;">
     29                     <div class="login-center-input-text">密码</div>
     30                 </div>
     31             </div>
     32             <div class="login-center clearfix">
     33                 <div class="login-center-img"><img th:src="@{/xadmin/login/images/cpacha.png}"></div>
     34                 <div class="login-center-input">
     35                     <input style="50%;" type="text" name="cpacha" id="cpacha" value="" placeholder="请输入验证码" onfocus="this.placeholder=&#39;&#39;" onblur="this.placeholder=&#39;请输入验证码&#39;">
     36                     <div class="login-center-input-text">验证码</div>
     37                     <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()">
     38                 </div>
     39             </div>
     40             <div class="login-button">
     41                 登录
     42             </div>
     43         </div>
     44         <div class="sk-rotating-plane"></div>
     45 <canvas class="particles-js-canvas-el" width="1147" height="952" style=" 100%; height: 100%;"></canvas></div>
     46 
     47 <!-- scripts -->
     48 <script th:src="@{/xadmin/login/js/particles.min.js}"></script>
     49 <script th:src="@{/xadmin/login/js/app.js}"></script>
     50 <script th:src="@{/xadmin/login/js/jquery-1.8.0.min.js}"></script>
     51 <script type="text/javascript">
     52     function hasClass(elem, cls) {
     53       cls = cls || '';
     54       if (cls.replace(/s/g, '').length == 0) return false; //当cls没有参数时,返回false
     55       return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ');
     56     }
     57 
     58     function addClass(ele, cls) {
     59       if (!hasClass(ele, cls)) {
     60         ele.className = ele.className == '' ? cls : ele.className + ' ' + cls;
     61       }
     62     }
     63 
     64     function removeClass(ele, cls) {
     65       if (hasClass(ele, cls)) {
     66         var newClass = ' ' + ele.className.replace(/[	
    ]/g, '') + ' ';
     67         while (newClass.indexOf(' ' + cls + ' ') >= 0) {
     68           newClass = newClass.replace(' ' + cls + ' ', ' ');
     69         }
     70         ele.className = newClass.replace(/^s+|s+$/g, '');
     71       }
     72     }
     73 
     74     function changeCpacha(){
     75         $("#cpacha-img").attr("src",'get_cpacha?vl=4&w=150&h=40&type=loginCpacha&t=' + new Date().getTime());
     76     }
     77         document.querySelector(".login-button").onclick = function(){
     78                 var userName = $("#username").val();
     79                 var passWord = $("#password").val();
     80                 var cpacha = $("#cpacha").val();
     81                 if(userName == '' || userName == 'undefined'){
     82                     alert("请填写用户名!");
     83                     return;
     84                 }
     85                 if(passWord == '' || passWord == 'undefined'){
     86                     alert("请填写密码!");
     87                     return;
     88                 }
     89                 if(cpacha == '' || cpacha == 'undefined'){
     90                     alert("请填写验证码!");
     91                     return;
     92                 }
     93                 addClass(document.querySelector(".login"), "active")
     94                 addClass(document.querySelector(".sk-rotating-plane"), "active")
     95                 document.querySelector(".login").style.display = "none"
     96                 $.ajax({
     97                     url:'/login',
     98                     data:{userName:userName,passWord:passWord,cpacha:cpacha},
     99                     type:'post',
    100                     dataType:'json',
    101                     success:function(results){
    102                         if(results.code == 200){
    103                             window.parent.location = '/index';
    104                             //alert("登录成功!");
    105                         }else{
    106                             removeClass(document.querySelector(".login"), "active");
    107                             removeClass(document.querySelector(".sk-rotating-plane"), "active");
    108                             document.querySelector(".login").style.display = "block";
    109                             alert(results.msg);
    110                             changeCpacha();
    111                         }
    112                     }
    113                 });
    114 
    115         }
    116 </script>
    117 </body></html>
    login.html

    验证码--随机数字输入验证,原理:向服务端请求,生成随机的字符,写入会话请求,同时将随机字符生成对应图片,响应给前端;前端输入对应字符的验证码,向后台发起校验。

    这种没必要死记,网上这种一搜大把,只要理解其实现原理就行,不会就直接复制粘贴

      1 package com.beilin.util;
      2 
      3 import java.awt.Color;
      4 import java.awt.Font;
      5 import java.awt.Graphics;
      6 import java.awt.Graphics2D;
      7 import java.awt.image.BufferedImage;
      8 import java.util.Random;
      9 
     10 /**
     11  * 验证码生成器
     12  *
     13  * @author llq
     14  */
     15 public class CpachaUtil {
     16 
     17     /**
     18      * 验证码来源
     19      */
     20     final private char[] code = {
     21         '2', '3', '4', '5', '6', '7', '8', '9',
     22         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
     23         'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v',
     24         'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F',
     25         'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
     26         'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
     27     };
     28     /**
     29      * 字体
     30      */
     31     final private String[] fontNames = new String[]{
     32             "黑体", "宋体", "Courier", "Arial",
     33             "Verdana", "Times", "Tahoma", "Georgia"};
     34     /**
     35      * 字体样式
     36      */
     37     final private int[] fontStyles = new int[]{
     38             Font.BOLD, Font.ITALIC|Font.BOLD
     39     };
     40 
     41     /**
     42      * 验证码长度
     43      * 默认4个字符
     44      */
     45     private int vcodeLen = 4;
     46     /**
     47      * 验证码图片字体大小
     48      * 默认17
     49      */
     50     private int fontsize = 25;
     51     /**
     52      * 验证码图片宽度
     53      */
     54     private int width = (fontsize+1)*vcodeLen+10;
     55     /**
     56      * 验证码图片高度
     57      */
     58     private int height = fontsize+12;
     59     /**
     60      * 干扰线条数
     61      * 默认3条
     62      */
     63     private int disturbline = 3;
     64 
     65 
     66     public CpachaUtil(){}
     67 
     68     /**
     69      * 指定验证码长度
     70      * @param vcodeLen 验证码长度
     71      */
     72     public CpachaUtil(int vcodeLen) {
     73         this.vcodeLen = vcodeLen;
     74         this.width = (fontsize+1)*vcodeLen+10;
     75     }
     76 
     77     /**
     78      * 指定验证码长度、图片宽度、高度
     79      * @param vcodeLen
     80      * @param width
     81      * @param height
     82      */
     83     public CpachaUtil(int vcodeLen,int width,int height) {
     84         this.vcodeLen = vcodeLen;
     85         this.width = width;
     86         this.height = height;
     87     }
     88 
     89     /**
     90      * 生成验证码图片
     91      * @param vcode 要画的验证码
     92      * @param drawline 是否画干扰线
     93      * @return
     94      */
     95     public BufferedImage generatorVCodeImage(String vcode, boolean drawline){
     96         //创建验证码图片
     97         BufferedImage vcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
     98         Graphics g = vcodeImage.getGraphics();
     99         //填充背景色
    100         g.setColor(new Color(246, 240, 250));
    101         g.fillRect(0, 0, width, height);
    102         if(drawline){
    103             drawDisturbLine(g);
    104         }
    105         //用于生成伪随机数
    106         Random ran = new Random();
    107         //在图片上画验证码
    108         for(int i = 0;i < vcode.length();i++){
    109             //设置字体
    110             g.setFont(new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize));
    111             //随机生成颜色
    112             g.setColor(getRandomColor());
    113             //画验证码
    114             g.drawString(vcode.charAt(i)+"", i*fontsize+10, fontsize+5);
    115         }
    116         //释放此图形的上下文以及它使用的所有系统资源
    117         g.dispose();
    118 
    119         return vcodeImage;
    120     }
    121     /**
    122      * 获得旋转字体的验证码图片
    123      * @param vcode
    124      * @param drawline 是否画干扰线
    125      * @return
    126      */
    127     public BufferedImage generatorRotateVCodeImage(String vcode, boolean drawline){
    128         //创建验证码图片
    129         BufferedImage rotateVcodeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    130         Graphics2D g2d = rotateVcodeImage.createGraphics();
    131         //填充背景色
    132         g2d.setColor(new Color(246, 240, 250));
    133         g2d.fillRect(0, 0, width, height);
    134         if(drawline){
    135             drawDisturbLine(g2d);
    136         }
    137         //在图片上画验证码
    138         for(int i = 0;i < vcode.length();i++){
    139             BufferedImage rotateImage = getRotateImage(vcode.charAt(i));
    140             g2d.drawImage(rotateImage, null, (int) (this.height * 0.7) * i, 0);
    141         }
    142         g2d.dispose();
    143         return rotateVcodeImage;
    144     }
    145     /**
    146      * 生成验证码
    147      * @return 验证码
    148      */
    149     public String generatorVCode(){
    150         int len = code.length;
    151         Random ran = new Random();
    152         StringBuffer sb = new StringBuffer();
    153         for(int i = 0;i < vcodeLen;i++){
    154             int index = ran.nextInt(len);
    155             sb.append(code[index]);
    156         }
    157         return sb.toString();
    158     }
    159     /**
    160      * 为验证码图片画一些干扰线
    161      * @param g
    162      */
    163     private void drawDisturbLine(Graphics g){
    164         Random ran = new Random();
    165         for(int i = 0;i < disturbline;i++){
    166             int x1 = ran.nextInt(width);
    167             int y1 = ran.nextInt(height);
    168             int x2 = ran.nextInt(width);
    169             int y2 = ran.nextInt(height);
    170             g.setColor(getRandomColor());
    171             //画干扰线
    172             g.drawLine(x1, y1, x2, y2);
    173         }
    174     }
    175     /**
    176      * 获取一张旋转的图片
    177      * @param c 要画的字符
    178      * @return
    179      */
    180     private BufferedImage getRotateImage(char c){
    181         BufferedImage rotateImage = new BufferedImage(height, height, BufferedImage.TYPE_INT_ARGB);
    182         Graphics2D g2d = rotateImage.createGraphics();
    183         //设置透明度为0
    184         g2d.setColor(new Color(255, 255, 255, 0));
    185         g2d.fillRect(0, 0, height, height);
    186         Random ran = new Random();
    187         g2d.setFont(new Font(fontNames[ran.nextInt(fontNames.length)], fontStyles[ran.nextInt(fontStyles.length)], fontsize));
    188         g2d.setColor(getRandomColor());
    189         double theta = getTheta();
    190         //旋转图片
    191         g2d.rotate(theta, height/2, height/2);
    192         g2d.drawString(Character.toString(c), (height-fontsize)/2, fontsize+5);
    193         g2d.dispose();
    194 
    195         return rotateImage;
    196     }
    197     /**
    198      * @return 返回一个随机颜色
    199      */
    200     private Color getRandomColor(){
    201         Random ran = new Random();
    202         return new Color(ran.nextInt(220), ran.nextInt(220), ran.nextInt(220));
    203     }
    204     /**
    205      * @return 角度
    206      */
    207     private double getTheta(){
    208         return ((int) (Math.random()*1000) % 2 == 0 ? -1 : 1)*Math.random();
    209     }
    210 
    211     /**
    212      * @return 验证码字符个数
    213      */
    214     public int getVcodeLen() {
    215         return vcodeLen;
    216     }
    217     /**
    218      * 设置验证码字符个数
    219      * @param vcodeLen
    220      */
    221     public void setVcodeLen(int vcodeLen) {
    222         this.width = (fontsize+3)*vcodeLen+10;
    223         this.vcodeLen = vcodeLen;
    224     }
    225     /**
    226      * @return 字体大小
    227      */
    228     public int getFontsize() {
    229         return fontsize;
    230     }
    231     /**
    232      * 设置字体大小
    233      * @param fontsize
    234      */
    235     public void setFontsize(int fontsize) {
    236         this.width = (fontsize+3)*vcodeLen+10;
    237         this.height = fontsize+15;
    238         this.fontsize = fontsize;
    239     }
    240     /**
    241      * @return 图片宽度
    242      */
    243     public int getWidth() {
    244         return width;
    245     }
    246     /**
    247      * 设置图片宽度
    248      * @param width
    249      */
    250     public void setWidth(int width) {
    251         this.width = width;
    252     }
    253     /**
    254      * @return 图片高度
    255      */
    256     public int getHeight() {
    257         return height;
    258     }
    259     /**
    260      * 设置图片高度
    261      * @param height
    262      */
    263     public void setHeight(int height) {
    264         this.height = height;
    265     }
    266     /**
    267      * @return 干扰线条数
    268      */
    269     public int getDisturbline() {
    270         return disturbline;
    271     }
    272     /**
    273      * 设置干扰线条数
    274      * @param disturbline
    275      */
    276     public void setDisturbline(int disturbline) {
    277         this.disturbline = disturbline;
    278     }
    279 
    280 }
    验证码工具类

    (与登录相关的操作都放在LoginController,里面都有中文注解,很多东西只可意会不可言传)

     1 package com.beilin.controller;
     2 
     3 
     4 import com.beilin.Service.UserService;
     5 import com.beilin.entity.SysUser;
     6 import com.beilin.result.ResponseCode;
     7 import com.beilin.result.Results;
     8 import com.beilin.util.CpachaUtil;
     9 import com.beilin.util.Md5Cipher;
    10 import org.springframework.beans.factory.annotation.Autowired;
    11 import org.springframework.stereotype.Controller;
    12 import org.springframework.web.bind.annotation.*;
    13 import org.springframework.web.servlet.ModelAndView;
    14 
    15 import javax.imageio.ImageIO;
    16 import javax.servlet.http.HttpServletRequest;
    17 import javax.servlet.http.HttpServletResponse;
    18 import java.awt.image.BufferedImage;
    19 import java.io.IOException;
    20 
    21 /**
    22  * 系统登录控制器相关
    23  */
    24 @Controller
    25 public class LoginController {
    26     @Autowired
    27     private UserService userService;
    28 
    29 
    30     /**
    31      * 登录成功后的主页
    32      * @param model
    33      * @return
    34      */
    35     @GetMapping("/index")
    36     public ModelAndView index(ModelAndView model) {
    37         model.setViewName("index");
    38         return model;
    39     }
    40 
    41     /**
    42      * 打开登录页面
    43      * @param model
    44      * @return
    45      */
    46     @GetMapping("/login")
    47     public ModelAndView login(ModelAndView model) {
    48         model.setViewName("login");
    49         return model;
    50     }
    51 
    52  
    53     /**
    54      * 本系统所有的验证码均采用此方法
    55      * @param vcodeLen
    56      * @param width
    57      * @param height
    58      * @param cpachaType:用来区别验证码的类型,传入字符串
    59      * @param request
    60      * @param response
    61      */
    62     @GetMapping (value="/get_cpacha")
    63     public void generateCpacha(
    64             @RequestParam(name="vl",required=false,defaultValue="4") Integer vcodeLen,
    65             @RequestParam(name="w",required=false,defaultValue="100") Integer width,
    66             @RequestParam(name="h",required=false,defaultValue="30") Integer height,
    67             @RequestParam(name="type",required=true,defaultValue="loginCpacha") String cpachaType,
    68             HttpServletRequest request,
    69             HttpServletResponse response){
    70         //调用CpachaUtil中的构造方法指定验证码的长度,宽度,高度
    71         CpachaUtil cpachaUtil = new CpachaUtil(vcodeLen, width, height);
    72         //生成验证码
    73         String generatorVCode = cpachaUtil.generatorVCode();
    74         request.getSession().setAttribute(cpachaType, generatorVCode);
    75         //把随机取到的验证码传入图片 true--需要干扰线
    76         BufferedImage generatorRotateVCodeImage = cpachaUtil.generatorRotateVCodeImage(generatorVCode, true);
    77         try {
    78             ImageIO.write(generatorRotateVCodeImage, "gif", response.getOutputStream());
    79         } catch (IOException e) {
    80             // TODO Auto-generated catch block
    81             e.printStackTrace();
    82         }
    83     }
    84 
    85 
    86 }
    LoginControlle

    配置没问题就实现验证码功能了

     

  • 相关阅读:
    图片 滚动切换效果(五) 高级篇
    图片 滚动切换效果(四)
    图片 滚动切换效果(三)
    图片 滚动切换效果(二)
    图片 滚动切换效果(一)
    新年第一篇 之 (摄像机可视区域)
    SuperSocket源码解析之开篇 (转)
    矮人国之战 之 阵型 模仿(二)
    Web Service
    XML于JSON
  • 原文地址:https://www.cnblogs.com/wx60079/p/12805015.html
Copyright © 2011-2022 走看看