vue+django实现图片验证码验证

博客介绍了图片验证码的获取与验证流程,前端挂载页面时生成UUID请求验证码,后端生成并存储到Redis后返回图片。还给出后端接口代码、前端Vue项目创建及代码编写步骤,最后提及了django跨域配置测试。
  • 获取图片验证码、验证图片验证码

  • 一、流程:

    • 1、前端在挂载页面时生成唯一的UUID向后端发起请求获取图片验证码
    • 2、后端接受请求并生成图片验证码,并以UUID为键,图片验证码的文本为值,以一定的有效期存储至redis服务器中
    • 3、后端将生成的图片验证码以图片类型返回给前端
    • 4、前端接受显示
    • 5、用户将页面上显示的验证码输入文本框、点击验证,并携带验证码以及UUID向后端发起请求
    • 6、后端接受请求,接受参数,校验参数。
    • 7、后端从redis中取出当前UUID验证码的文本,并与前端传入的验证码进行比对。
    • 7、后端返回相应的响应信息
  •  二、后端接口代码:

  • import json
    from django.views import View
    from auth.captcha.captcha import captcha
    from django_redis import get_redis_connection
    from django import http
    
    
    
    class GenerateImageCode(View):
        def get(self, request, uuid):
            """
            :param request: 请求对象
            :param uuid: 唯一标识图形验证码所属于的用户
            :return: image/jpg
            """
            # 生成图片验证码
            text, image = captcha.generate_captcha()
    
            # 保存图片验证码
            redis_conn = get_redis_connection('verify_code') #获取redis连接对象
            redis_conn.setex('img_%s' % uuid, 120, text) # 以img_uuid为key存储图片验证码的文本
    
            # 响应图片验证码
            return http.HttpResponse(image, content_type='image/jpg')
    from django.urls import re_path
    from auth.views import GenerateImageCode
    
    urlpatterns = [
        re_path(r'^image_code/(?P<uuid>[\w-]+)/$', GenerateImageCode.as_view())
    ]
  • 三、前端代码的定义编写

    • 1、使用npm create project 在前端创建一个vue项目
    • 2、新建vue项目后,在vue.config.js中配置跨域请求代理
    • const { defineConfig } = require('@vue/cli-service')
      module.exports = defineConfig({
        transpileDependencies: true,
        
        lintOnSave:false,
        
        devServer: {
          open: true,
          host: 'localhost',
          port: 8080,
          https: false,
          //以上的ip和端口是我们本机的;下面为需要跨域的
          proxy: {//配置跨域
              '/api': {
                  target: 'http://127.0.0.1:8000',//这里后台的地址模拟的;应该填写你们真实的后台接口
                  ws: true,
                  changOrigin: true,//允许跨域
                  pathRewrite: {
                      '^/api': ''//请求的时候使用这个api就可以
                  }
                  //rewrite:(path)=>path.replace(/^\/api/,"")
              }
      
          }
      }
      })
      
    • 3、新建一个command.js文件用于生成唯一的UUID
    • var generateUUID=function(){
          let d = new Date().getTime();
          if(window.performance && typeof window.performance.now === "function"){
              d += performance.now(); //use high-precision timer if available
          }
          let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
              let r = (d + Math.random()*16)%16 | 0;
              d = Math.floor(d/16);
              return (c=='x' ? r : (r&0x3|0x8)).toString(16);
          });
          return uuid;
      }
      export {
          generateUUID
      }
    • 4、新建一个login.vue组件,并编写相应逻辑代码
    • <template>
          <div id="master">
              <label for="">图形验证码:</label>
              <input type="text" v-model="input_image_code">
              <img :src="image_code" alt="" @click="get_image_code"><br/>
              <span v-show="show_errmsg_status">{{show_errmsg}}</span>
              <button @click="check_image_code">验证</button><br/>      
          </div>
      </template>
      <script>
      
      import axios from 'axios' 
      import { generateUUID } from '@/js/command' //导入command.js
          export default {
              
              data() {
                  return {
                      image_code: '',
                      input_image_code:'',
                      UUID:'',
                      show_errmsg:'',
                      show_errmsg_status:false
                  }
              },
              methods: {
                  get_image_code() {
                      this.UUID=generateUUID()
                      this.image_code='http://127.0.0.1:8000/image_code/'+ this.UUID 
                  },
                  // 获取文本框中输入的验证码,向后端发起请求验证验证码
                  check_image_code(){
                      axios.post('/api/image_code/'+this.UUID+'/',{
                          image_code:this.input_image_code,
                          responseType: 'json',
                      })
                      .then((res)=>{
                          if(res.data.errmsg==='ok'){
                              this.show_errmsg_status=true;
                              this.show_errmsg='验证成功'
                          }else{
                              this.show_errmsg_status=true;
                              this.show_errmsg='验证失败'
                          }
                      })
                      .catch(err=>{
                          console.log('失败')
                      })
                  }
              },
              mounted () {
                  // 页面挂载后调用方法获取后端验证码显示在页面上
                  this.get_image_code();
              },
          }
      </script>
      
      <style scoped>
          *{
              margin: 0px;
              padding: 0px;
          }
          #master{
              text-align: center;
          }
          label{
              color: grey;
          }
          img{
              width: 100px;
              height: 30px;
              padding-top: 10px;
          }
      </style>
    • 5、在router文件夹下的index.js中配置login组件的路由
    • { path:'/login', name:'login',component:()=>import('@/views/login')},
    • 6、在main.js下导入router使用router
    • import Vue from 'vue'
      import App from './App.vue'
      import router from './router'
      
      
      
      Vue.config.productionTip = false
      
      new Vue({
        router,
        render: h => h(App)
      }).$mount('#app')
    • 7、在app.vue下使用router视图
      <template>
        <div id="app">
          
            <!-- home视图 -->
            <router-view></router-view> 
            
      </div>
      </template>

  • 四、测试 (django跨域配置

     

<think>我们被要求实现一个使用VueDjango的登录注册功能。根据引用,我们可以总结出以下步骤: 1. 项目结构:通常将Vue项目放在Django项目的一个子目录中(例如`web`文件夹),并将Vue构建后的静态文件(dist)放入该目录。同时,在Vue项目中创建static文件夹作为静态资源(引用[2])。 2.后端交互:Vue前端通过HTTP请求与Django后端交互。我们可以使用axios或类似库来发送请求(引用[3]展示了使用封装的request方法)。 3. Django后端:需要创建视图函数来处理注册和登录请求,并返回JSON响应(引用[4]展示了如何编写一个处理POST请求的视图函数,并返回JsonResponse)。 4. 跨域问题:在开发阶段,由于前端后端可能运行在不同端口,需要处理CORS(跨域资源共享)。可以使用Django的`django-cors-headers`中间件来解决。 5. 认证机制:登录成功后,后端可以返回一个认证令牌(例如JWT)或使用Django的session机制来保持用户登录状态。 具体步骤: **后端Django)部分:** 1. 创建Django应用(如果还没有),例如`account`,用于处理用户认证。 2. 在`settings.py`中安装必要的应用和中间件,包括`corsheaders`(用于跨域)和`rest_framework`(可选,用于简化API开发,但非必须)。 3. 创建用户模型(Django自带`User`模型,可以直接使用)。 4. 编写注册和登录的视图函数: - 注册:接收用户名、密码等信息,创建新用户。 - 登录:验证用户名和密码,如果正确,可以生成一个令牌(或使用Django的`authenticate`和`login`函数来创建session)。 5. 配置URL路由。 **前端Vue)部分:** 1. 创建登录和注册的组件(页面)。 2. 在表单提交时,调用一个方法,该方法使用axios(或类似库)向后端发送POST请求。 3. 处理响应,如果成功,则保存返回的令牌(或session信息)到本地(例如localStorage或Vuex store),并跳转到主页;如果失败,显示错误信息。 下面我们分别给出代码示例: **后端Django视图示例(注册和登录):** ```python # 在views.py中 from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.contrib.auth import authenticate, login from django.contrib.auth.models import User import json @csrf_exempt def register(request): if request.method == 'POST': try: data = json.loads(request.body) username = data.get('username') password = data.get('password') email = data.get('email', '') # 检查用户名是否已存在 if User.objects.filter(username=username).exists(): return JsonResponse({'error': '用户名已存在'}, status=400) # 创建用户 user = User.objects.create_user(username, email, password) # 可以在这里进行额外的设置,比如保存其他信息 return JsonResponse({'message': '注册成功'}, status=201) except Exception as e: return JsonResponse({'error': str(e)}, status=400) return JsonResponse({'error': '只接受POST请求'}, status=405) @csrf_exempt def user_login(request): if request.method == 'POST': data = json.loads(request.body) username = data.get('username') password = data.get('password') # 验证用户 user = authenticate(request, username=username, password=password) if user is not None: login(request, user) # 这会设置session return JsonResponse({'message': '登录成功'}) else: return JsonResponse({'error': '用户名或密码错误'}, status=400) return JsonResponse({'error': '只接受POST请求'}, status=405) ``` **前端Vue示例(使用axios发送请求):** 首先,在Vue组件中,我们设置两个表单,分别用于注册和登录。 注册组件(Register.vue)示例: ```vue <template> <div> <form @submit.prevent="register"> <input type="text" v-model="username" placeholder="用户名"> <input type="email" v-model="email" placeholder="邮箱"> <input type="password" v-model="password" placeholder="密码"> <button type="submit">注册</button> </form> </div> </template> <script> import axios from 'axios'; export default { data() { return { username: '', email: '', password: '' } }, methods: { register() { axios.post('http://localhost:8000/register/', { username: this.username, email: this.email, password: this.password }, { headers: { 'Content-Type': 'application/json' } }) .then(response => { alert(response.data.message); // 注册成功后跳转到登录页面 this.$router.push('/login'); }) .catch(error => { alert(error.response.data.error); }); } } } </script> ``` 登录组件(Login.vue)类似: ```vue <template> <div> <form @submit.prevent="login"> <input type="text" v-model="username" placeholder="用户名"> <input type="password" v-model="password" placeholder="密码"> <button type="submit">登录</button> </form> </div> </template> <script> import axios from 'axios'; export default { data() { return { username: '', password: '' } }, methods: { login() { axios.post('http://localhost:8000/login/', { username: this.username, password: this.password }, { headers: { 'Content-Type': 'application/json' }, withCredentials: true // 允许发送cookie(用于session认证) }) .then(response => { alert(response.data.message); // 登录成功后跳转到主页 this.$router.push('/'); }) .catch(error => { alert(error.response.data.error); }); } } } </script> ``` **注意:** - 由于我们使用了`@csrf_exempt`装饰器,暂时禁用了CSRF保护,但在生产环境中应该考虑启用CSRF保护,并在前端获取CSRF令牌(Django会在cookie中设置`csrftoken`,前端可以在请求头中设置`X-CSRFToken`)。 - 跨域问题:在开发环境中,确保已经配置了`django-cors-headers`。安装包`pip install django-cors-headers`,然后在`settings.py`中添加: ```python INSTALLED_APPS = [ ... 'corsheaders', ... ] MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ] # 允许所有来源(仅开发) CORS_ALLOW_ALL_ORIGINS = True # 允许携带凭证(如cookie) CORS_ALLOW_CREDENTIALS = True ``` - 生产环境中,应设置`CORS_ALLOWED_ORIGINS`为前端的实际地址。 以上代码示例提供了一个基本的登录注册功能实现。根据实际需求,可能还需要添加更多的验证和功能,比如密码确认、密码强度、验证码等。 最后,配置Django的URL: ```python # urls.py from django.urls import path from .views import register, user_login urlpatterns = [ path('register/', register, name='register'), path('login/', user_login, name='login'), ] ``` 这样,前后端就可以通过`/register/`和`/login/`路径进行交互了。 **相关问题:** 1. 如何在前端保存登录状态(例如使用Vuex)? 2. 如何实现Django的CSRF保护与Vue的集成? 3. 如何使用JWT(JSON Web Token)代替session进行认证? 4. 如何实现用户退出登录(logout)功能? 5. 如何在前端显示登录后的用户信息?</think>### VueDjango实现登录注册功能的前后端交互方案 #### 一、项目结构规划 参考引用[2],推荐以下结构: ``` django_project/ ├── manage.py ├── backend/ # Django应用 │ ├── settings.py │ ├── urls.py │ └── views.py └── frontend/ # Vue项目 ├── public/ ├── src/ │ ├── api/ # 接口封装 │ ├── router/ # 路由配置 │ ├── store/ # Vuex状态管理 │ └── views/ # 页面组件 ``` #### 二、后端实现Django) 1. **用户模型**:使用Django内置`User`模型 ```python # models.py (可选扩展) from django.contrib.auth.models import AbstractUser class CustomUser(AbstractUser): phone = models.CharField(max_length=15, blank=True) ``` 2. **注册接口**(参考引用[4]): ```python # views.py from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.contrib.auth.models import User import json @csrf_exempt def register(request): if request.method == 'POST': try: data = json.loads(request.body) username = data['username'] password = data['password'] email = data.get('email', '') # 创建用户 user = User.objects.create_user( username=username, password=password, email=email ) return JsonResponse({ 'status': 'success', 'user_id': user.id }, status=201) except KeyError: return JsonResponse({'error': '缺少必要参数'}, status=400) except Exception as e: return JsonResponse({'error': str(e)}, status=400) return JsonResponse({'error': '仅支持POST请求'}, status=405) ``` 3. **登录接口**: ```python # views.py from django.contrib.auth import authenticate, login @csrf_exempt def user_login(request): if request.method == 'POST': data = json.loads(request.body) username = data['username'] password = data['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) # 创建session return JsonResponse({ 'status': 'success', 'user': user.username }) return JsonResponse({'error': '无效凭证'}, status=401) return JsonResponse({'error': '仅支持POST请求'}, status=405) ``` #### 三、前端实现Vue 3 + Composition API) 1. **API服务封装**(参考引用[3]): ```javascript // src/api/auth.js import axios from 'axios' const api = axios.create({ baseURL: 'http://localhost:8000/api/', withCredentials: true // 携带cookie用于session认证 }) export const register = (userData) => api.post('register/', userData) export const login = (credentials) => api.post('login/', credentials) export const checkAuth = () => api.get('check_auth/') ``` 2. **注册组件**: ```vue <!-- src/views/Register.vue --> <script setup> import { ref } from 'vue' import { register } from '@/api/auth' const form = ref({ username: '', password: '', email: '' }) const submit = async () => { try { const response = await register(form.value) console.log('注册成功:', response.data) // 跳转到登录页 } catch (error) { console.error('注册失败:', error.response.data) } } </script> <template> <form @submit.prevent="submit"> <input v-model="form.username" placeholder="用户名"> <input v-model="form.password" type="password" placeholder="密码"> <input v-model="form.email" type="email" placeholder="邮箱"> <button type="submit">注册</button> </form> </template> ``` 3. **登录组件**: ```vue <!-- src/views/Login.vue --> <script setup> import { ref } from 'vue' import { useRouter } from 'vue-router' import { login } from '@/api/auth' const credentials = ref({ username: '', password: '' }) const router = useRouter() const submit = async () => { try { await login(credentials.value) router.push('/dashboard') // 跳转到受保护页面 } catch (error) { console.error('登录失败:', error.response.data) } } </script> ``` #### 四、关键配置项 1. **Django跨域设置**(重要!): ```python # settings.py INSTALLED_APPS = [ ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:8080", # Vue开发服务器 ] CORS_ALLOW_CREDENTIALS = True # 允许携带cookie ``` 2. **路由配置**: ```python # urls.py from django.urls import path from . import views urlpatterns = [ path('register/', views.register), path('login/', views.user_login), path('check_auth/', views.check_auth), ] ``` #### 五、认证状态管理 1. **Django会话检查**: ```python # views.py def check_auth(request): if request.user.is_authenticated: return JsonResponse({ 'authenticated': True, 'username': request.user.username }) return JsonResponse({'authenticated': False}, status=401) ``` 2. **Vue前端状态管理**: ```javascript // src/store/auth.js import { defineStore } from 'pinia' import { checkAuth } from '@/api/auth' export const useAuthStore = defineStore('auth', { state: () => ({ user: null, isAuthenticated: false }), actions: { async checkAuthentication() { try { const res = await checkAuth() this.user = res.data.username this.isAuthenticated = true } catch { this.isAuthenticated = false } } } }) ``` #### 六、安全增强措施 1. **CSRF保护**(生产环境必需): ```python # 前端在axios请求头添加: const csrfToken = getCookie('csrftoken') // 从cookie获取 api.defaults.headers.common['X-CSRFToken'] = csrfToken # Django视图移除@csrf_exempt装饰器 ``` 2. **密码加密**: - Django默认使用PBKDF2加密 - 传输层使用HTTPS 3. **输入验证**: ```python # 示例:Django表单验证 from django import forms class RegistrationForm(forms.Form): username = forms.CharField(min_length=4) password = forms.CharField(widget=forms.PasswordInput, min_length=8) email = forms.EmailField(required=False) ``` --- ### 相关问题 1. 如何处理Django的CSRF令牌与Vue的集成? 2. 如何实现JWT认证替代Session认证? 3. 用户登录后如何在前端管理认证状态? 4. 如何实现密码重置功能? 5. 第三方登录(如Google/OAuth2)如何集成? 6. 如何设计权限控制系统(RBAC)?
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值