国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

菜鳥級(jí):Vue Element-UI 前端 + Flask 后端 的登錄頁(yè)面驗(yàn)證碼

這篇具有很好參考價(jià)值的文章主要介紹了菜鳥級(jí):Vue Element-UI 前端 + Flask 后端 的登錄頁(yè)面驗(yàn)證碼。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

這里記錄登錄頁(yè)面驗(yàn)證碼的做法,采取的是前后端分離的做法,前端用Vue,后端用Flask

首先是GIF效果圖:

菜鳥級(jí):Vue Element-UI 前端 + Flask 后端 的登錄頁(yè)面驗(yàn)證碼

后端返回的數(shù)據(jù)結(jié)構(gòu)(base64字符串,response.data.img):

菜鳥級(jí):Vue Element-UI 前端 + Flask 后端 的登錄頁(yè)面驗(yàn)證碼

?

1、Vue前端頁(yè)面基本采用Ruoyi Ui里面的登錄頁(yè)面代碼,里面的一些方法進(jìn)行重寫;

  • 首先是單個(gè)vue文件里網(wǎng)頁(yè)內(nèi)容<template></template>部分:
<template>
  <div class="login">
    <el-form
      ref="loginForm"
      :model="loginForm"
      :rules="loginRules"
      class="login-form"
    >
      <h3 class="title">通用后臺(tái)管理系統(tǒng)</h3>
      <el-form-item prop="username">
        <el-input
          v-model="loginForm.username"
          type="text"
          auto-complete="off"
          placeholder="賬號(hào)"
          prefix-icon="el-icon-user"
        >
        </el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input
          v-model="loginForm.password"
          type="password"
          auto-complete="off"
          placeholder="密碼"
          @keyup.enter.native="handleLogin"
          prefix-icon="el-icon-lock"
          show-password
        >
        </el-input>
      </el-form-item>
      <el-form-item prop="code" v-if="captchaOnOff">
        <el-input
          v-model="loginForm.code"
          auto-complete="off"
          placeholder="驗(yàn)證碼"
          style="width: 63%"
          @keyup.enter.native="handleLogin"
          prefix-icon="el-icon-key"
        >
        </el-input>
        <div class="login-code">
          <img :src="codeUrl" @click="getCode" class="login-code-img" />
        </div>
      </el-form-item>
      <el-checkbox
        v-model="loginForm.rememberMe"
        style="margin: 0px 0px 25px 0px"
        >記住密碼</el-checkbox>
      <el-form-item style="width: 100%">
        <el-button
          :loading="loading"
          size="medium"
          type="primary"
          style="width: 100%"
          @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">登 錄</span>
          <span v-else>登 錄 中...</span>
        </el-button>
        <div style="float: right" v-if="register">
          <router-link class="link-type" :to="'/register'"
            >立即注冊(cè)</router-link
          >
        </div>
      </el-form-item>
    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
      <span>Copyright ? 2021-2022 VIP.vip All Rights Reserved.</span>
    </div>
  </div>
</template>
  • 交互方法<Script></Script>部分:

1) Axios請(qǐng)求配置。

function get(url, params, response_type) {
    let newAxios = axios.create()
    let promise;
    // 請(qǐng)求超時(shí)時(shí)間
    newAxios.defaults.timeout = 10000;
    return new Promise((resolve, reject) => {
        promise = newAxios.get(url, {
            params: params,
            responseType: response_type
        });
        promise.then((response) => {
            resolve(response);
        }).catch(error => {
            reject(error);
        })
    })
}
Vue.prototype.get = get

2) toLogin登錄方法。

export function toLogin(data) {
	return this.get('/login/toLogin', [data])
}

3) 其他js代碼,其中setToken,setUserInfo,setInstId,removeAll方法不重要,這些方法是登錄后保存一些用戶信息用的,因此讀者可自行忽略掉。

<script>
import { toLogin } from "@/api/login.js";
import {
  setToken,
  setUserInfo,
  setInstId,
  removeAll,
} from "../../utils/permission";
export default {
  name: "Login",
  data() {
    return {
      codeUrl: "",
      loginForm: {
        username: "admin",
        password: "123456",
        rememberMe: false,
        code: "",
        uuid: "",
      },
      loginRules: {
        username: [
          { required: true, trigger: "blur", message: "請(qǐng)輸入您的賬號(hào)" },
        ],
        password: [
          { required: true, trigger: "blur", message: "請(qǐng)輸入您的密碼" },
        ],
        code: [{ required: true, trigger: "change", message: "請(qǐng)輸入驗(yàn)證碼" }],
      },
      loading: false,
      // 驗(yàn)證碼開關(guān)
      captchaOnOff: true,
      // 注冊(cè)開關(guān)
      register: false,
      redirect: undefined,
    };
  },
  watch: {
    $route: {
      handler: function (route) {
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true,
    },
  },
  created() {
    this.getCode();
  },
  methods: {
    getCode() {
      this.get("/getImgCode").then((res) => {
        this.codeUrl = res.data.img;
      });
    },
    // 登錄請(qǐng)求
    handleLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          let _this = this;
          toLogin(_this.loginForm)
            .then((res) => {
              removeAll(); //清除所有本地緩存
              if (res.status === 200) {
                this.$store.commit("getUserId", res.data.userInfo.ID);
                setToken(res.data.token);
                let fixedUserInfo = res.data.userInfo;
                this.get(
                  "/myinfo_img_download",
                  [fixedUserInfo.img, fixedUserInfo.ID, "login"],
                  ""
                ).then((res) => {
                  if (res.data.code != 200) {
                    _this.$message.error(res.data.msg);
                    fixedUserInfo.img = res.data.imgs;
                    setUserInfo(JSON.stringify(fixedUserInfo));
                    _this.$router.push("/");
                  } else {
                    fixedUserInfo.img = res.data.imgs;
                    setUserInfo(JSON.stringify(fixedUserInfo));
                    _this.$router.push("/");
                  }
                });
                setInstId(res.data.inst_id);
                _this.showMsg(res.data.userInfo.nickname);
              } else if (res.status === 201) {
                _this.$message({
                  message: "該用戶已被停用!",
                  type: "warning",
                });
              } else if (res.status === 304) {
                _this.$message({
                  message: "驗(yàn)證碼錯(cuò)誤!",
                  type: "error",
                });
              } else if (res.status === 500) {
                _this.$message({
                  message: "密碼錯(cuò)誤!",
                  type: "error",
                });
              } else {
                _this.$message({
                  message: "用戶名不存在!",
                  type: "error",
                });
              }
            })
            .catch((err) => {
              console.log(err);
            });
        }
      });
    },
    // 消息通知
    showMsg(realName) {
      this.$notify({
        title: "提示",
        dangerouslyUseHTMLString: true,
        message: "尊敬的<strong>" + realName + "</strong>,歡迎回來(lái)。",
        type: "success",
        duration: 2000,
      });
    },
  },
};
</script>

4) CSS代碼,注意background-image中的圖片要自己準(zhǔn)備。

<style rel="stylesheet/scss" lang="scss">
.login {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background-image: url("../../assets/images/login-background.jpg");
  background-size: cover;
}
.title {
  margin: 0px auto 30px auto;
  text-align: center;
  color: #707070;
  font-weight: 600;
  font-size: 21px;
}

.login-form {
  border-radius: 6px;
  background: #ffffff;
  width: 400px;
  padding: 25px 25px 5px 25px;
  .el-input {
    height: 38px;
    input {
      height: 38px;
    }
  }
  .input-icon {
    height: 39px;
    width: 14px;
    margin-left: 2px;
  }
}
.login-tip {
  font-size: 13px;
  text-align: center;
  color: #bfbfbf;
}
.login-code {
  width: 33%;
  height: 38px;
  float: right;
  display: flex;

  img {
    margin-left: 10px;
    position: relative;
    top: -3px;
    cursor: pointer;
    vertical-align: middle;
  }
}
.el-login-footer {
  height: 40px;
  line-height: 40px;
  position: fixed;
  bottom: 0;
  width: 100%;
  text-align: center;
  color: #fff;
  font-family: Arial;
  font-size: 12px;
  letter-spacing: 1px;
}
.login-code-img {
  height: 38px;
}
</style>

login-backg.jpg?

菜鳥級(jí):Vue Element-UI 前端 + Flask 后端 的登錄頁(yè)面驗(yàn)證碼?

2、Flask的代碼則參考另外一篇網(wǎng)上的代碼段。

from flask import Flask, render_template,\
    request, jsonify, make_response, Response, send_file,session,send_from_directory
from flask_cors import CORS
import json
import base64

app = Flask(__name__)
''' 解決后端跨域問(wèn)題,不然會(huì)在前端網(wǎng)頁(yè)控制臺(tái)顯示“ccess to XMLHttpRequest at 'http://localhost:8080/api/login' from origin 'null' has been blocked” '''
CORS(app, supports_credentials=True)
# 存儲(chǔ)驗(yàn)證碼
session = {}

# 前端Login界面調(diào)取驗(yàn)證碼圖片,返回JSON字符串,非blob數(shù)據(jù)類型
@app.route('/getImgCode', methods=["GET", "POST"])
def imgCode():
  res = imageCode().getImgCode()
  return jsonify({"img":res})

# -------------------------------- #
# from io import BytesIO
import random
import string
from PIL import Image, ImageFont, ImageDraw, ImageFilter
# 生成驗(yàn)證碼
class imageCode():
    '''驗(yàn)證碼處理'''
    def rndColor(self):
        '''隨機(jī)顏色'''
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
    def geneText(self): 
        '''生成4位驗(yàn)證碼'''
        # ascii_letters是生成所有字母 digits是生成所有數(shù)字0-9
        imgCode = ''.join(random.sample(string.ascii_letters + string.digits, 4))
        return imgCode
    def drawLines(self, draw, num, width, height):
        '''劃線'''
        for num in range(num):
          x1 = random.randint(0, width / 2)
          y1 = random.randint(0, height / 2)
          x2 = random.randint(0, width)
          y2 = random.randint(height / 2, height)
          draw.line(((x1, y1), (x2, y2)), fill='black', width=1)
    def getVerifyCode(self):
        '''生成驗(yàn)證碼圖形'''
        code = self.geneText()
        # 圖片大小120×50
        width, height = 120, 50
        # 新圖片對(duì)象
        im = Image.new('RGB', (width, height), 'white')
        # 字體
        font = ImageFont.truetype('app/static/arial.ttf', 40)
        # draw對(duì)象
        draw = ImageDraw.Draw(im)
        # 繪制字符串
        for item in range(4):
            draw.text((5 + random.randint(-3, 3) + 23 * item, 5 + random.randint(-3, 3)),
               text=code[item], fill=self.rndColor(), font=font)
        # 劃線,參數(shù)1為畫板,參數(shù)2為線條數(shù)量,參數(shù)3為寬度,參數(shù)4為高度
        self.drawLines(draw, 2, width, height)
        return im, code
    def getImgCode(self):
        image, code = self.getVerifyCode()
        session['imageCode'] = code
        file_path =r"./upload/loginPic.jpg"
        image.save(file_path)
        # 把驗(yàn)證碼圖片的base64字段作為response返回前端,類型是string
        with open(file_path, 'rb') as img_f:
            img_stream = img_f.read()
            img_stream = base64.b64encode(img_stream)
            base64_string = img_stream.decode('utf-8')
            base64_string = "data:image/png;base64," + base64_string
            return base64_string

if __name__ == '__main__':
    # 0.0.0.0 表示同一個(gè)局域網(wǎng)均可訪問(wèn),也可以替換成本機(jī)地址:通過(guò)命令行命令:ipcofig 獲取
    app.run(host='0.0.0.0', port='5000', debug=True)

上面geneText是生產(chǎn)隨機(jī)字母和數(shù)字結(jié)合的驗(yàn)證碼內(nèi)容的方法,此步比較關(guān)鍵

然后是PIL(Pillow)庫(kù)畫圖的方法了:


ImageDraw.Draw.text()是在給定位置繪制字符串,生成圖片返回Web端使用。ImageDraw.Draw.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align=”left”)

ImageDraw.Draw.line()是在給定xy的數(shù)組,fill的填充顏色,線的寬度情況下劃線ImageDraw.Draw.line(xy, fill=None, width=0)

最后以返回圖片的base64字符串給前端即可?

3、參考網(wǎng)址:?

flask驗(yàn)證碼https://www.qb5200.com/article/361920.html文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-403396.html

到了這里,關(guān)于菜鳥級(jí):Vue Element-UI 前端 + Flask 后端 的登錄頁(yè)面驗(yàn)證碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Vue2 +Element-ui實(shí)現(xiàn)前端頁(yè)面

    Vue2 +Element-ui實(shí)現(xiàn)前端頁(yè)面

    以一個(gè)簡(jiǎn)單的前端頁(yè)面為例。主要是利用vue和element-ui實(shí)現(xiàn)。 里面涉及的主要包括:新建vue項(xiàng)目、一行多個(gè)輸入框、頁(yè)面實(shí)現(xiàn)等。 ? ①首先安裝nodejs,這部分在此就不講啦。 ②然后安裝vue-cli: 查看是否安裝成功: 安裝成功之后就輸出vue的版本 ③在cmd窗口新建一個(gè)vue2腳手架

    2024年02月16日
    瀏覽(35)
  • vue搭配element-ui前端實(shí)現(xiàn)表格分頁(yè)

    如果不從后臺(tái)請(qǐng)求數(shù)據(jù),那么就需要在前端手動(dòng)管理數(shù)據(jù)??梢允褂靡韵虏襟E實(shí)現(xiàn)該功能: 在 Vue 組件的 data 中定義一個(gè)數(shù)組來(lái)存放所有數(shù)據(jù)(不分頁(yè))。 在 mounted 鉤子函數(shù)中,手動(dòng)獲取數(shù)據(jù)并存放到上一步定義的數(shù)組中。 在模板中使用 element-ui 的表格組件來(lái)展示數(shù)據(jù),同

    2024年02月11日
    瀏覽(32)
  • 用element-ui中的up-load組件實(shí)現(xiàn)簡(jiǎn)單的圖片上傳到本地然后回顯(從前端到后端)

    用element-ui中的up-load組件實(shí)現(xiàn)簡(jiǎn)單的圖片上傳到本地然后回顯(從前端到后端)

    一:前端樣式以及效果: ?前端樣式代碼如下: 二:后端Controller層 ?這里的處理邏輯是將前端傳遞進(jìn)來(lái)的圖片交給FileUtil處理,接下來(lái)看FileUtil的代碼: 首先獲取傳遞進(jìn)來(lái)圖片的文件名后綴 然后用UUID將其拼接得到一個(gè)新的名字 將圖片存入到本地的文件夾下面 接下來(lái)返回路

    2024年02月03日
    瀏覽(27)
  • 簡(jiǎn)單的vue+element-ui純前端實(shí)現(xiàn)基本增刪改查功能

    簡(jiǎn)單的vue+element-ui純前端實(shí)現(xiàn)基本增刪改查功能

    建立一個(gè)vue2的項(xiàng)目: 打開控制臺(tái),輸入命令:vue create xxx(項(xiàng)目名稱,記得要小寫哈),并回車,記得選擇vue2 ?用vscode打開項(xiàng)目,并 引入相關(guān)的依賴 打開項(xiàng)目 終端,輸入命令 npm i element-ui -S npm install less-loader@5.0.0 --save ?npm install less --save 點(diǎn)擊進(jìn)入main.js,引入elementui ,加上下面

    2024年02月06日
    瀏覽(33)
  • Vue element-ui form 表單 前端提交和后端的接收

    一、前端 1、新建彈窗dialog 2、在數(shù)據(jù)(data)里面綁定(return)數(shù)據(jù) 3、在method里新建方法 二、后端 1、在配置好mybatis-plus的前提下 2、在控制類中添加方法 3、@RequestBody注解的使用 @requestBody注解的使用 - 西風(fēng)惡 - 博客園 (cnblogs.com)

    2024年02月15日
    瀏覽(26)
  • vue腳手架創(chuàng)建項(xiàng)目:賬號(hào)登錄(利用element-ui快速開發(fā))(取消eslint強(qiáng)制格式)(修改端口號(hào))

    vue腳手架創(chuàng)建項(xiàng)目:賬號(hào)登錄(利用element-ui快速開發(fā))(取消eslint強(qiáng)制格式)(修改端口號(hào))

    新手看不懂,老手不用看系列 創(chuàng)建好項(xiàng)目以后,可以利用idea等工具打開項(xiàng)目。 file - open 然后選擇創(chuàng)建好項(xiàng)目文件夾,信任該項(xiàng)目 然后打開 .vue 后綴的文件需要下載一個(gè)插件 就是把eslint這個(gè)相關(guān)的配置刪除掉(注意保持JSON格式) 點(diǎn) terminal 打開命令行輸入 npm install element-u

    2024年04月28日
    瀏覽(32)
  • vue前端直接使用element-ui的upload組件上傳到阿里云OSS存儲(chǔ)

    vue前端直接使用element-ui的upload組件上傳到阿里云OSS存儲(chǔ)

    因?yàn)楣镜姆?wù)器比較拉吧,所以老大決定將數(shù)據(jù)文件等上傳到阿里云服務(wù)器,通過(guò)ali-oss方式,這樣的話讀取文件也比較快? (能看到這說(shuō)明什么安裝element-ui都會(huì)了,我就不詳細(xì)介紹了,直接跳過(guò))? 在執(zhí)行下面操作之前,你要確定你的阿里云能看到上邊這個(gè)頁(yè)面? ?這里主

    2024年02月10日
    瀏覽(37)
  • 2022.9.17 vue、element-ui實(shí)現(xiàn)登錄獲取手機(jī)驗(yàn)證碼,進(jìn)行手機(jī)號(hào)校驗(yàn)、驗(yàn)證碼CD60秒

    2022.9.17 vue、element-ui實(shí)現(xiàn)登錄獲取手機(jī)驗(yàn)證碼,進(jìn)行手機(jī)號(hào)校驗(yàn)、驗(yàn)證碼CD60秒

    1、直接點(diǎn)擊,不為空校驗(yàn) 2、輸入手機(jī)號(hào)格式不正確時(shí) 3、獲取完驗(yàn)證碼進(jìn)行讀秒 三、vue 1、進(jìn)行手機(jī)號(hào)校驗(yàn)關(guān)鍵在對(duì)單個(gè)手機(jī)號(hào)輸入框進(jìn)行校驗(yàn),需要使用到validateField對(duì)部分表單字段進(jìn)行校驗(yàn),valid是校驗(yàn)完的提示信息,當(dāng)valid為空時(shí)代表校驗(yàn)成功 2、讀秒和設(shè)置禁用,在校

    2024年02月11日
    瀏覽(32)
  • 前端css + js +vue +element-ui 實(shí)現(xiàn)響應(yīng)式布局,根據(jù)瀏覽器窗體大小自動(dòng)響應(yīng)

    我的環(huán)境是element-ui vue版的,其他的也可以,主要是css和js的內(nèi)容 首先在data中定義一個(gè)對(duì)象 其實(shí)就是css的樣式,不過(guò)放在了js 里面而已 這里css設(shè)置了兩個(gè)屬性 一個(gè)是transform 這個(gè)屬性對(duì)div標(biāo)簽的縮放作用,當(dāng)瀏覽器窗口或者屏幕大小改變時(shí),就調(diào)整這個(gè)屬性的值,來(lái)等比縮放

    2024年02月13日
    瀏覽(35)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包