精华内容
下载资源
问答
  • 1、是作为背景图片的展示,很抱歉一直没有试出来 护体的方法了参考的地址有 ... 这种还算比较实用的,可是额,他并没有解决我的...2、然后是单纯座位图片的展示使用img标签 这个作者https://www.cnblogs.com/can-i-do/
    1、是作为背景图片的展示,很抱歉一直没有试出来
    护体的方法了参考的地址有
    这种还算比较实用的,可是额,他并没有解决我的问题,因为我需要这个图片是可以更新的,这里是死的

    2、然后是单纯座位图片的展示使用img标签
    额,不知道是他表达能力不好还是我理解能力尚不行,既然他说的解答一是不行的那为什么不贴出来解答二的方法呐,真是so~~
    反正最后我是这样实现的贴出我的代码
    <img :src="imageBase64" alt="">
    self.imageBase64 = 'data:image/png;base64,'+res.data.body.imageBase64;
    展开全文
  • 图形验证码的处理封装 前后端跨域处理(这里处理的是vue和静态资源服务器端口不同导致验证码跨域问题) 前端分析: vue框架 登录视图页面 axios 发送请求(这里是封装了axios) 获取数据 2、np

    vue中使用验证码

    1、思路分析

    后端分析:

    1. nodejs的第三方express 开启服务器
    2. 数据接口 —— 包括登录接口、图形验证接口
    3. 图形验证码的处理封装
    4. 前后端跨域处理(这里处理的是vue和静态资源服务器端口不同导致验证码跨域问题)

    前端分析:

    1. vue框架 登录视图页面
    2. axios 发送请求(这里是封装了axios) 获取数据

    2、npm安装必要的包

    npm i express 开启静态资源服务器
    npm i mongodb 连接数据库
    npm i express-session 会话session
    npm i svg-captcha 图形验证码
    npm i jsonwebtoken 用于令牌的token

    注意以下以 nodejs 和 mongodb 来后端和数据库开发使用,以 nodejs 的第三方 express 开启静态资源服务器使用

    3、express开启服务器和封装必要的请求函数

    server.js

    const express = require('express');
    const {
      PORT
    } = require('./config.json');
    const rootRouter = require('./router');
    const path = require('path')
    
    //创建一个服务器
    const app = express();
    
    //  ./ 是当前目录 
    //   / 是根目录
    // 启用静态资源服务器
    app.use(express.static(path.join(__dirname, './public'), {
      // maxAge:60*60*1000*24
    }));
    
    // 数据接口
    app.use('/api', rootRouter);
    
    app.listen(PORT, () => {
      console.log('server is running on port ' + PORT)
    })
    

    router文件下的index.js

    const {
      Router,
      urlencoded,
      json
    } = require('express');
    // express.json===bodyParse.json, ....
    
    const session = require('express-session')
    const token = require('../utils/token');
    const cors = require('../utils/cors')
    
    const router = Router();
    
    const userRouter = require('./user');
    const goodsRouter = require('./goods');
    
    const regRouter = require('./reg');
    const loginRouter = require('./login');
    
    const vcodeRouter = require('./vcode');
    const uploadRouter = require('./upload');
    
    const {
      formatData
    } = require('../utils/tools');
    
    // 跨域请求处理
    router.use(cors)
    
    // 数据格式化中间件
    router.use(urlencoded({
      extended: false
    }), json())
    
    // 使用session会话
    // 通过req.session获取存入会话的数据
    router.use(session({
      secret: 'fqniu',
      resave: false,
      saveUninitialized: true,
      cookie: {
        // 设置cookie有效期
        maxAge: 1000 * 60 * 60 * 2
      }
    }))
    
    // /api/user
    router.use('/user', userRouter);
    
    // /api/goods
    router.use('/goods', goodsRouter);
    
    // 注册
    router.use('/reg', regRouter);
    
    // 登录
    router.use('/login', loginRouter);
    
    // 上传
    router.use('/upload', uploadRouter);
    
    // 校验token
    router.get('/jwtverify', (req, res) => {
      const {
        authorization
      } = req.query;
      console.log('test', authorization)
    
      // verify方法校验成功:得到一个对象
      // verify方法校验不通过:直接抛出错误
      // try{
      //     var decoded = jwt.verify(authorization, 'laoxie');
      //     res.send(formatData())
      // }catch(err){
      //     res.send(formatData({code:0}))
      // }
    
      if (token.verify(authorization)) {
        res.send(formatData())
      } else {
        res.send(formatData({
          code: 0
        }))
      }
    });
    
    // 验证码
    router.use('/vcode', vcodeRouter);
    
    
    module.exports = router;
    

    router文件下的mongodb.js

    /**
     * MongoDB操作封装
     */
    const {
      MongoClient,
      ObjectId
    } = require('mongodb');
    
    // mongodb数据库地址
    const url = 'mongodb://localhost:27017';
    
    // 数据库名称
    const dbName = 'user';
    
    async function connect() {
      const client = await MongoClient.connect(url);
      const db = client.db(dbName);
      return {
        client,
        db
      }
    }
    
    
    // 增
    async function insert(colName, data) {
      // 1. 连接数据库
      const {
        db,
        client
      } = await connect();
      // 2. 添加数据
    
      // 根据传入的集合名称获取数据库中的某个集合
      const collection = db.collection(colName);
    
      const result = await collection[Array.isArray(data) ? 'insertMany' : 'insertOne'](data)
    
      // 3. 关闭连接
      client.close()
      return result;
    }
    
    // 删
    async function remove(colName, query) { // query{_id:'5c128cdbd1233ce12c878a32'}
      const {
        db,
        client
      } = await connect();
    
      if (query._id && typeof query._id === 'string') {
        query._id = ObjectId(query._id);
      }
    
      const collection = db.collection(colName);
      const result = await collection.deleteMany(query);
    
      client.close();
      return result;
    }
    
    // 改
    async function update(colName, query, newData) { // newData{$set:{price:200,qty:2},$inc:{view:1}}
      const {
        db,
        client
      } = await connect();
    
      const collection = db.collection(colName);
    
      if (query._id && typeof query._id === 'string') {
        query._id = ObjectId(query._id);
      }
    
      const result = await collection.updateMany(query, newData);
    
      return result;
    }
    
    // 查  query 查询语句
    async function find(colName, query = {}, options = {}) { // options={litmit:10,skip:0}
      const {
        client,
        db
      } = await connect();
      // console.log("query=", query)
    
      const collection = db.collection(colName);
    
      if (query._id && typeof query._id === 'string') {
        query._id = ObjectId(query._id);
      }
    
      // // 查询多少条数据
      let datalength = await collection.count().then(data => data)
      // console.log("数据长度=", datalength) // 50
      // 添加条数
      let total = datalength
      // console.log("这个1=", result)
    
      // 如果存在query查询到的 name 则执行下面语句
      if (query.name) {
        const font = query.name
        let result = collection.find({
          'name': {
            '$regex': font,
            // "$options": 'i'
          }
        });
        result = await result.toArray();
        client.close();
        return {
          result,
          total
        }
      }
    
      // 查询到数据集合
      let result = collection.find(query); // 50->10
    
      // 判断是否要跳过记录
      if (options.skip) {
        result = result.skip(options.skip)
      }
    
      if (options.limit) {
        result = result.limit(options.limit);
      }
    
      // 排序
      // console.log('sort',options.sort);
      if (options.sort) { //['price'],['price','1']
        let key, val;
        key = options.sort[0];
        if (options.sort.length > 1) {
          val = options.sort[1] * 1;
        } else {
          val = -1;
        }
        result = result.sort({
          [key]: val
        })
      }
    
      result = await result.toArray();
      // console.log(result)
      client.close();
      
      // 把数据和数据长度返回出去
      return {
        result,
        total
      }
    }
    
    
    module.exports = {
      insert,
      remove,
      update,
      find
    }
    

    router文件下的vcode.js

    const express = require('express');
    const router = express.Router();
    const svgCaptcha = require('svg-captcha');
    
    const {
      formatData
    } = require('../utils/tools');
    
    // 生成验证码
    router.get('/', async (req, res) => {
      // 生成图像验证码:svg-captcha
      const options = {
        // size: 10,
        noise: 3,
        ignoreChars: '0o1il',
        background: '#58bc58',
        color: true,
        fontSize: 50,
        height: 54
      }
    
      // 验证码在这里生成
      const captcha = svgCaptcha.create(options); // {data:'<svg/>',text:'abcd'}
    
      //  console.log('vcode.session=',req.session);
      // 把验证码存入会话Session
      req.session.vcode = captcha.text.toLowerCase();
    
      res.send(formatData({
        data: captcha.data
      }));
    })
    
    module.exports = router;
    

    router文件下的token.js

    const jwt = require('jsonwebtoken');
    
    const privateKey = 'fqniu';
    
    function create(data = {}, expiresIn = '2h') {
      const token = jwt.sign({
        ...data
      }, privateKey, {
        // token有效期
        expiresIn
      });
      return token;
    }
    
    function verify(token) {
      let result;
      try {
        jwt.verify(token, privateKey);
        result = true;
      } catch (err) {
        result = false
      }
      return result;
    }
    
    module.exports = {
      create,
      verify
    }
    

    router文件下的login.js

    const express = require('express');
    const router = express.Router();
    
    // 引入 封装的 token 模块
    const token = require('../utils/token');
    
    const {
      formatData,
      md5
    } = require('../utils/tools');
    const mongo = require('../utils/mongo');
    
    // 登录 get请求
    router.get('/', async (req, res) => {
        let { username, password, vcode, mdl } = req.query;
        // 其中vcode是前端输入的验证码
        // 从会话中获取验证码
        // 校验验证码 这里的req.session 是已经存有vcode的 Session 对象
        // console.log('login.session=', req.session)
        // vcode 是前端输入验证码之后,传过来的参数 
        // 而 req.session.vcode 是Session中的存的 vcode
        if (vcode !== req.session.vcode) {
            res.send(formatData({ code: 10 }))
            return;
        }
        // 加密后进行查询
        // password = md5(password)
        let {result} = await mongo.find('user', { username, password }); //[{}]
        console.log("result=",result)
        // 判断如果 find 找到 有result, 则返回这个数组数据
        // 如果find 找不到 ,则result为 空数组
        if (result.length > 0) {
            // 用户名、密码、验证码都校验通过后,判断是否有免登陆选项
            // console.log('req.query=', req.query);
            let authorization;
            if (mdl === 'true') {
                // token的操作
                // 1. 生成token
                // const token = jwt.sign({ username }, 'laoxie' ,{
                //     // token有效期
                //     expiresIn: 20//1000 * 60 * 60 * 24 * 7
                // });
                //封装的 token 函数
                authorization = token.create({ username }, '7d')
            }else{
                authorization = token.create({ username })
            }
            // console.log('token=', authorization);
            result = result[0];
            result.authorization = authorization
            res.send(formatData({ data: result }));
        } else {
            res.send(formatData({ code: 0 }))
        }
    })
    
    module.exports = router;
    

    router文件下的cors.js
    用于跨域处理

    const allow_origin = ['localhost:3000', 'www.xxxxxx.com']
    
    function cors(req, res, next) {
      // 设置响应头
      // Access-Control-Allow-Origin
      // Access-Control-Allow-Methods
      // Access-Control-Allow-Headers
      // res.header("Access-Control-Allow-Origin", "*");
      // res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
      // res.header("Access-Control-Allow-Methods","PUT,POST,GET,PATCH,DELETE,OPTIONS");
      // console.log('Origin:',req.get('host'));
    
      // 获取请求者的域名
      if (allow_origin.includes(req.get('host'))) {
        res.set({
          "Access-Control-Allow-Origin": "http://localhost:8080",
          "Access-Control-Allow-Headers": "Content-Type,Content-Length, Authorization, Accept,X-Requested-With",
          "Access-Control-Allow-Methods": "PUT,POST,GET,PATCH,DELETE,OPTIONS",
          "Access-Control-Allow-Credentials": true
        })
        // 跨域请求CORS中的预请求
        if (req.method == "OPTIONS") {
          res.sendStatus(200); /*让options请求快速返回*/
        } else {
          next();
        }
      } else {
        res.send(401);
      }
    }
    
    module.exports = cors;
    

    router文件下的tools.js
    用于对请求数据formatData的封装

    const crypto = require('crypto');
    
    function formatData({code=1, data=[], msg='success'}={}){
    
        if(code === 0){
          msg = 'fail';
        }
    
        return {
          code,
          data,
          msg
        }
    }
    
    // 封装加密函数
    function md5(data,privateKey='fqniu'){
    
      const hash = crypto.createHash('md5');
      hash.update(data + privateKey); // 加盐 盐值
      const result = hash.digest('hex');
      return result;
    }
    
    
    module.exports = {
      formatData,
      md5
    }
    

    4、前端准备工作

    <template>
      <div class="login-wrap">
        <el-form class="login-form" :model="ruleForm" status-icon ref="ruleForm" label-width="100px">
          <h1>登录账号</h1>
          <el-form-item label="用户名" prop="username">
            <el-input type="text" v-model="ruleForm.username" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="验证码" class="vcode-input">
            <el-input placeholder="请输入验证码" v-model="ruleForm.vcode">
              <!-- 验证码html结构 -->
              <template v-slot:append>
                <div v-html="vcodeSvg" @click="vcode()" class="vcode"></div>
              </template>
            </el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click.prevent="submitForm()">登录</el-button>
            <el-button @click="resetForm">重置</el-button>
            <el-button @click="gotoLogin">立即注册</el-button>
          </el-form-item>
        </el-form>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          // from表单 参数 需要发请求到后端进行处理, 包括用户名、密码、验证码
          ruleForm: {
            username: "admin",
            password: "123456",
            vcode: "",
          },
          // 定义变量接收请求后的图形验证码
          vcodeSvg: "",
        };
      },
      methods: {
        // 登录请求
        async submitForm() {
          const { data } = await this.$request.get("/login", {
            // 因为后端需要 query 来接收参数,所以这里需要传入params { 里面放出去的参数 }
            // 这是对象需要结构
            params: {
              ...this.ruleForm,
            },
          });
          console.log(data);
          if (data.code === 1) {
            // 登录成功
            // 保存token
            localStorage.setItem("token", data.data.authorization);
            this.$message({
              type: "success",
              message: "登录成功",
            });
            // 登录成功跳转到home
            this.$router.push("/home");
          } else if (data.code === 10) {
            // 登录失败
            this.$message({
              type: "error",
              message: "验证码有误",
            });
          } else {
            this.$message({
              type: "error",
              message: "账号和密码有误",
            });
          }
        },
        // 重置表单数据
        resetForm() {
          this.ruleForm.username = "";
          this.ruleForm.password = "";
        },
        // 点击注册按钮, 跳转到注册
        gotoLogin() {
          this.$router.push("/reg");
        },
        // 点击更新验证码
        async vcode() {
          const { data } = await this.$request.get("/vcode");
          // console.log(data);
          this.vcodeSvg = data.data;
        },
      },
      // vue生命周期中created函数, 一加载页面时就发请求 显示图形验证码 并把返回的数据渲染到页面上
      // 因为后端返回的是图形验证码的html
      created() {
        this.vcode();
      },
    };
    </script>
    
    <style>
    .login-wrap {
      height: 100%;
      background: #ccc;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .login-form {
      width: 520px;
      padding: 20px;
      background: #fff;
      border-radius: 10px;
    }
    .el-input .el-input-group__append {
      padding: 0;
      border: 0;
    }
    .vcode svg {
      width: 110px;
      height: 40px;
    }
    </style>
    

    效果图:
    在这里插入图片描述

    5、遇到问题

    但是虽然验证码获取数据渲染页面成功,发送登录请求,但是后端却返回验证码有误,经过多次验证和查资料,才发现的问题如下:

    问题如图:
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    5、问题处理

    这里是处理图形验证码后端session中获取不到的问题(跨域)也就是 跨域导致 set-cookie 无效
    推荐博客跨域set-cookie无效

    后端处理cors跨域:
    在这里插入图片描述
    前端处理axios发送请求
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    还有一种是前后端已经设置了,但是还是拿不到vcode怎么办?

    最终发现是浏览器因为安全策略给禁用了cookie,比如谷歌的 chrome://flags/ 里面的设置
    在这里插入图片描述

    展开全文
  • This is a digital graphic verification code written in canvas(这是一个vue的插件,使用canvas来生成图形验证码)
  • Vue 图形验证码实现 详解

    万次阅读 2019-07-15 13:26:02
    其实绘制图形二维码就是使用 进行图形绘制 canvas 绘制图形 1.获取元素dom 访问绘图上下文 <canvas id="tutorial" width="150" height="150"></canvas> var canvas = document.getElementById('...

    其实绘制图形二维码就是使用 进行图形绘制

    canvas 绘制图形

    1.获取元素dom 访问绘图上下文

    <canvas id="tutorial" width="150" height="150"></canvas>
    var canvas = document.getElementById('tutorial'); //获取dom
    var ctx = canvas.getContext('2d'); //访问绘图上下文

    2.第二步就是绘制相应内容了,下面是vue 绘制验证码图形

    如图:[在这里插入图片描述](https://img-blog.csdnimg.cn/2019071512072254.png在这里插入图片描述

    1.父组件login.vue
    <template>
        <div class="login-wrap">
            <div class="ms-login">
                <div class="ms-title">后台管理系统</div>
                <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="0px" class="ms-content">
                    <el-form-item prop="username">
                        <el-input v-model="ruleForm.username" placeholder="username">
                            <el-button slot="prepend" icon="el-icon-people"></el-button>
                        </el-input>
                    </el-form-item>
                    <el-form-item prop="password">
                        <el-input type="password" placeholder="password" v-model="ruleForm.password" @keyup.enter.native="submitForm('ruleForm')">
                            <el-button slot="prepend" icon="el-icon-lock"></el-button>
                        </el-input>
                    </el-form-item>
    
                    <el-form-item prop="sidentify"> // 验证码
                        <el-col :span="14">
                        <el-input placeholder="sidentify" v-model="ruleForm.password" @keyup.enter.native="submitForm('ruleForm')">
                        </el-input>
                        </el-col>
                        <el-col :span="8">
                            <v-sidentify></v-sidentify>
                        </el-col>
                    </el-form-item>
                    <div class="login-btn">
                        <el-button type="primary" @click="submitForm('ruleForm')">登录</el-button>
                    </div>
                    <p class="login-tips">Tips : 用户名和密码随便填。</p>
                </el-form>
            </div>
        </div>
    </template>
    
    <script>
        import Sidentify from '../components/common/Sidentify'  //**引入验证码组件**
        export default {
            data: function(){
                return {
                    ruleForm: {
                        username: '',
                        password: '',
                        sidentify: '',
                    },
                    rules: {
                        username: [
                            { required: true, message: '请输入用户名', trigger: 'blur' }
                        ],
                        password: [
                            { required: true, message: '请输入密码', trigger: 'blur' }
                        ],
                        sidentify:[
                            {required: true}
                        ]
                    }
                }
            },
            components: {
                'v-sidentify':Sidentify 
            },
          
        }
    </script>
    
    2. 创建验证码组件
    <template>
        <div class="s-canvas">
            <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
        </div>
    </template>
    <script>
        export default {
            name: 'SIdentify',
            props: {
                identifyCode: {
                    type: String,
                    default: 'asdf'
                },
    
            },
            data(){
                return {
                    fontSizeMin: 160,
                    fontSizeMax: 40,
                    backgroundColorMin: 180,
                    backgroundColorMax:240,
                    colorMin: 50,
                    colorMax: 160,
                    lineColorMin:40,
                    lineColorMax: 180,
                    dotColorMin: 0,
                    dotColorMax: 255,
                    contentWidth: 112,
                    contentHeight: 38
                }
            },
            methods: {
                // 生成一个随机数
                randomNum(min, max) {
                    return Math.floor(Math.random() * (max - min) + min)
                },
                // 生成一个随机的颜色
                randomColor(min, max) {
                    let r = this.randomNum(min, max)
                    let g = this.randomNum(min, max)
                    let b = this.randomNum(min, max)
                    return 'rgb(' + r + ',' + g + ',' + b + ')'
                },
                drawPic() {
                    let canvas = document.getElementById('s-canvas')
                    let ctx = canvas.getContext('2d')
                    // ctx.textBaseline = 'bottom'
                    // 绘制背景
                    ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax) //图形填充颜色设置
                    ctx.strokeStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax) //图形轮廓的颜色设置
                    ctx.fillRect(0, 0, this.contentWidth, this.contentHeight) //绘制一个填充的矩形 0 0 width height x起点 y起点  宽 高
                    ctx.strokeRect(0,0,this.contentWidth, this.contentHeight) // 绘制一个矩形边框 0 0 width height x起点 y起点  宽 高
                    // ctx.clearRect(50,0,this.contentWidth,this.contentHeight)  //清除指定矩形区域,清除部分完全透明
                    // 绘制文字
                    for (let i = 0; i < this.identifyCode.length; i++) {
                        this.drawText(ctx, this.identifyCode[i], i)
                    }
                    this.drawLine(ctx)
                    this.drawDot(ctx)
                },
                drawText(ctx, txt, i) {
                    ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
                    ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei' //字体大小
                    ctx.textBaseline = 'alphabetic' //基线对齐
                    let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
                    let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
                    var deg = this.randomNum(-45, 45)
                    // 修改坐标原点和旋转角度
                    ctx.translate(x, y)//移动不同位置  参数偏移量
                    ctx.rotate(deg * Math.PI / 180) //旋转 参数角度
                    ctx.fillText(txt, 0, 0)
                    // 恢复坐标原点和旋转角度
                    ctx.rotate(-deg * Math.PI / 180)
                    ctx.translate(-x, -y)
                },
                drawLine(ctx) {
                    // 绘制干扰线
                    for (let i = 0; i < 8; i++) {
                        ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)
                        ctx.beginPath() //新建一条路径
                        ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) //设置起点x,y
                        ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) //绘制直线 x,y 一条当前位置到x,y点的直线
                        ctx.stroke() // 通过线条绘制图形轮廓
                        // ctx.closePath() //结束闭合路径
                    }
                },
                drawDot(ctx) {
                    // 绘制干扰点
                    for (let i = 0; i < 100; i++) {
                        ctx.fillStyle = this.randomColor(0, 255)
                        ctx.beginPath()
                        // 绘制圆弧或圆,x,y,radius,startAngle,endAngle,anticlockwise // x,y 圆心点,radius 半径,从startAngle开始到endAngle结束
                        ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)
                        ctx.fill() //通过填充路径的内容区域生成实心的图形。
                    }
                }
            },
            watch: {
                identifyCode() {
                    this.drawPic()
                }
            },
            mounted() {
                this.drawPic()
            }
        }
    </script>
    
    
    展开全文
  • ​ 5.1 使用标签直接引入图形验证码组件 ​ 5.2 在onShow页面初次渲染完成生命周期中调用组件中生成验证码方法 ​ 5.3 点击提交表单函数中,调用判断封装函数,将用户输入信息作为实参传入,可以得到一个布尔返回值 ​ ...

    源码
    https://gitee.com/he-dongjun/graphic-verification-code

    思路

    1.创建生成图形验证码的组件

    2.在main.js中全局注册图形验证码组件

    3.封装一个验证码校验的js文件

    4.使用vue.prototype实现验证码校验全局变量

    5.在表单页中

    ​ 5.1 使用标签直接引入图形验证码组件

    ​ 5.2 在onShow页面初次渲染完成生命周期中调用组件中生成验证码方法

    ​ 5.3 点击提交表单函数中,调用判断封装函数,将用户输入信息作为实参传入,可以得到一个布尔返回值

    ​ 5.4 返回值为false时,重新生成图形验证码

    1.创建生成图形验证码的组件

    components/picture_captcha/picture_captcha.vue

    <template>
    	<view class="canvas-img-code" @click="refresh()">
    		<text>图形验证码</text>
    		<canvas :style="{width:width+'px',height:height+'px'}" canvas-id="imgcanvas" @error="canvasIdErrorCallback"></canvas>
    	</view>
    </template>
    
    <script>
    	export default {
    		data() {
    			return {
    				
    			};
    		},
    		props:{
    			width:{
    				type:Number,
    				default:120
    			},
    			height:{
    				type:Number,
    				default:45
    			},
    			title:{
    				type:String,
    				default:'字符串'
    			},
    			boolean:{
    				type:Boolean,
    				default:false
    			},
    			array:{
    				type:Array,
    				default(){
    					return [1,2,3]
    				}
    			},
    			object:{
    				type:Object,
    				default(){
    					return {text:'标题'}
    				}
    			}
    		},
    		methods:{
    			// 初始化验证码
    			init: function() {
    				console.log('start');
    				var context = uni.createCanvasContext('imgcanvas', this),
    					w = this.width,
    					h = this.height;
    				context.setFillStyle("white");
    				context.setLineWidth(5);
    				context.fillRect(0, 0, w, h);
    				var pool = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "I", "M", "N", 								"O", "P", "Q", "R", "S","T", "U", "V", "W", "S", "Y", "Z", "1", "2", "3",                                  "4", "5", "6", "7", "8", "9", "0"
    					],
    					str = '';
    				for (var i = 0; i < 4; i++) {
    					var c = pool[this.rn(0, pool.length - 1)];
    					var deg = this.rn(-30, 30);
    					context.setFontSize(18);
    					context.setTextBaseline("top");
    					context.setFillStyle(this.rc(80, 150));
    					context.save();
    					context.translate(30 * i + 15, parseInt(h / 1.5));
    					context.rotate(deg * Math.PI / 180);
    					context.fillText(c, -15 + 5, -15);
    					context.restore();
    					str += c;
    				}
    				// 将图形码存储到本地
    				uni.setStorage({
    					key: 'imgcode',
    					data: str,
    				});
    				for (var i = 0; i < 40; i++) {
    					context.beginPath();
    					context.arc(this.rn(0, w), this.rn(0, h), 1, 0, 2 * Math.PI);
    					context.closePath();
    					context.setFillStyle(this.rc(150, 200));
    					context.fill();
    				}
    				context.draw();
    				console.log('end');
    			},
    			rc: function(min, max) {
    				var r = this.rn(min, max);
    				var g = this.rn(min, max);
    				var b = this.rn(min, max);
    				return "rgb(" + r + "," + g + "," + b + ")";
    			},
    			rn: function(max, min) {
    				return parseInt(Math.random() * (max - min)) + min;
    			},
    			refresh: function() {
    				this.init();
    			},
    			canvasIdErrorCallback: function(e) {
    				console.error(e.detail.errMsg)
    			}
    		}
    	}
    </script>
    
    <style lang="scss">
        
    </style>
    

    2.全局注册图形验证码组件

    main.js

    // 图形验证码
    import picture_captcha from '@/components/picture_captcha/picture_captcha.vue'
    Vue.component("picture-captcha",picture_captcha)
    

    3.封装一个验证码校验的js文件

    enterprise/util/Tools.js

    let Tools = {};
    // 提交判断
    Tools.formSubmit = (data, compare) => {
    	let {
    		value,
    	} = data;
    	for (var key in value) {
    		let values = value[key];
    		// 图形验证码 判断
    		if (key == 'verCode') {
    			if (values.length != 4) {
    				uni.showToast({
    					icon: 'none',
    					title: '图形验证码不正确!',
    					duration: 2500
    				});
    				return false;
    			}
    			// toLowerCase将字符串转换为小写
    			if (values.toLowerCase() != uni.getStorageSync('imgcode').toLowerCase()) {
    				uni.showToast({
    					icon: 'none',
    					title: '图形验证码不正确!',
    					duration: 2500
    				});
    				return false;
    			}
    		}
    		
    	}
    	return true;
    }
    module.exports = Tools;
    

    4.验证码校验全局变量

    // 将验证方法使用vue.prototype实现全局变量  在组件中通过this.tools来访问
    import Tools from  './util/Tools.js'
    Vue.prototype.tools = Tools;
    

    5.表单页中

    <template>
    	<view class="content">
    		<form @submit="formSubmit">
    			<view class="cu-form-group color32">
    				<input placeholder="请输入图形验证码" type="text" name="verCode" />
                      //生成图形验证码的组件
    				<picture-captcha ref="captcha" v-show="modalName == ''"></picture-captcha>
    				<button class="cu-btn submit" form-type="submit">点击验证</button>
    			</view>
    		</form>
    	</view>
    </template>
    
    <script>
    	export default {
    		data() {
    			return {
    				modalName: '',
    			}
    		},
    		
    		methods: {
    			formSubmit(e) {
    				let that = this; //获取外部this指向
    				let values = e.detail.value; //用户输入的信息
    				let click = that.click; //blonen布尔值
    
    				let data = {
    					check: {
    						verCode: '图形验证码',
    					},
    					value: values,
    				}
    				// 调用判断封装函数
    				var checks = that.tools.formSubmit(data);
    				// 验证不通过时,重新生成验证码
    				if(!checks){
    					that.$refs.captcha.init()
    				}
    
    			},
    		},
    		onShow() {
                // 页面初次渲染完成生成验证码
    			let that = this;
    			setTimeout(() => {
    				that.$refs.captcha.init()
    			}, 1000)
    		},
    	}
    </script>
    
    <style>
    	
    </style>
    
    
    展开全文
  • 一、vue 点击动态更新图形验证码 在验证码的图片上,绑定点击事件 getCaptcha(),同时使用 ref 指明图形验证码的引用对象,代码如下所示: <section class="login_message"> <input type="text" ...
  • 验证码使用流程和原理为:在服务器端负责生成图形验证码,并以数据流的形式供前端访问获取,同时将生成的验证码存储到全局的缓存中,在本案例中,我们使用redis作为全局缓存,并设置缓存失效时间。当用户使用...
  • 前端图形验证码组件

    2020-10-06 12:17:27
    4位,数字加大写字母的验证码 点击可以实现图片的变化 使用 1.克隆项目,主要代码在src/components/vue-img-verify.vue中 git clone https://github.com/luguanrui/vue-img-verify.git 2.演示代码 DOM: <vue-...
  • identify 是一个vue的组件,使用canvas来生成图形验证码。 identify: 在 components 文件夹下创建 identify.vue文件,代码如下 <template> <div class="s-canvas"> <canvas id="s-canvas" :width...
  • vue客户端的config>index.js中配置 /api = http://localhost:3000 src>api>index.js中配置基础路径 不能直接写 http://localhost:3000 保证vue组件中的所有服务器请求域名统一:http://localhost:3000 ...
  • 这是一个vue的插件,使用canvas来生成图形验证码。 具体参数如下: 直接上测试代码: identify.vue组件(主要用于定义参数和方法) <template> <div class="s-canvas"> <canvas id="s-canvas...
  • VUE接入腾讯云验证码

    2020-07-15 16:02:50
    腾讯云验证码-图形验证 目的:该模型能够准确识别可信、可疑和恶意用户,并提供不同的验证体验,令有效验证通过更轻松,机器作恶更困难。防止软件外围发短信被恶意攻击。 前提:接入验证码前,需要先在验证码...
  • NodeJS 使用 svg-captcha 模块实现图形验证码的功能,Vue的功能 效果图,每次点击验证码的时候就会发送一次请求 1. NodeJS方面 安装 npm i svg-captcha svg-captcha中文文档地址 在express中的使用方法const ...
  • identify是一款使用使用canvas来生成图形验证码vue插件。 代码: identify.vue组件(主要用于定义参数和方法) <template> <div class="s-canvas"> <canvas id="s-canvas" :width="contentWidth...
  • 这是一个vue的插件,使用canvas来生成图形验证码 具体参数如下: 在src\components\identify目录下创建identify.vue文件(主要用于定义参数和方法) 内容如下: <template> <div ...
  • 这是一个vue的插件,使用canvas来生成图形验证码 具体参数如下: 在src\components\identify目录下创建identify.vue文件(主要用于定义参数和方法) 内容如下: <template> <div class="s-canvas...
  • vue系列---identify(生成图片验证码)插件

    万次阅读 多人点赞 2018-01-16 10:45:06
    这是一个vue的插件,使用canvas来生成图形验证码。 具体参数如下: 直接上测试代码: identify.vue组件(主要用于定义参数和方法) template> div class="s-canvas"> canvas id="s-canvas" :width=...
  • 今天我们就要用 vue 实现一个电子签名的面板想要绘制图形,第一步想到的就是使用 canvas 标签,在之前的文章里我们使用 canvas 实现了一个前端生成图形验证码的组件,被吐槽不够安全,那么这个电子签名组件相比不会....
  • vue+element-ui集成随机验证码 转载自:https://blog.csdn.net/qq_39009348/article/details/81411432 登录窗口实现图形验证码 第一步:自定义一个生产随机验证码的组件,其本质是使用canvas绘制,详细代码如下: ...
  • 今天我们就要用vue实现一个电子签名的面板想要绘制图形,第一步想到的就是使用canvas标签,在之前的文章里我们使用canvas实现了一个前端生成图形验证码的组件,被吐槽不够安全,那么这个电子签名组件相比不会被吐槽...
  • 使用vue实现一个电子签名组件

    千次阅读 2020-01-03 16:26:30
    想要绘制图形,第一步想到的就是使用canvas标签,在之前的文章里我们使用canvas实现了一个前端生成图形验证码的组件,被吐槽不够安全,那么这个电子签名组件相比不会被吐槽了吧~ canvas <canvas> 标签是 ...
  • 想要绘制图形,第一步想到的就是使用canvas标签,在之前的文章里我们使用canvas实现了一个前端生成图形验证码的组件,被吐槽不够安全,那么这个电子签名组件想必不会被吐槽了吧~ canvas <canvas> 标签是 HTML 5 中...
  • Sidentify.vue

    2019-11-12 16:13:11
    图形验证码在前端页面是很常见,此插件(工具类)嵌入工程后可以直接使用,实现起来速度很快,使用非常的方便、简单,可以提高编码效率
  • VUE大坑-继续记录

    2019-08-01 17:06:09
    identify做图形验证码. 引入之后, 在html部分使用时,总是报 .......did you register the component correctly? 来, 先骂一波.... 这里有个坑. 引入时 import {这里的名字是驼峰的}, 例如: import {Sidentify } ...

空空如也

空空如也

1 2
收藏数 37
精华内容 14
关键字:

vue使用图形验证码

vue 订阅