vuex+vue-cookie+django用户认证相关

vue前端

npm install vuex
npm install vue-cookie

2、新建store.js文件:

# src/store/store.js
import Vue from 'vue'
import Vuex from 'vuex'
import Cookie from 'vue-cookies'

Vue.use(Vuex);

export default new Vuex.Store({
  // 组件中通过 this.$store.state.username 调用
  state: {
    username: Cookie.get("username"),
    token:Cookie.get("token"),
  },
  mutations: {
    // 组件中通过 this.$store.commit(saveToken,参数)  调用
    saveToken: function (state, userToken) {
      state.username = userToken.username;
      state.token = userToken.token;
      Cookie.set("username", userToken.username, "20min")
      Cookie.set("token", userToken.token, "20min")
    },
    clearToken: function (state) {
      state.username = null;
      state.token = null;
      Cookie.remove('username');
      Cookie.remove('token');
    }
  }

})
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

# 导入store.js文件
import store from './store/store'

new Vue({
  el: '#app',
  router,
  store,  # 在根实例中添加store配置文件
  components: {
    App,
  },
  template: '<App/>'
});


# 添加全局守卫,作用类似与中间件
router.beforeEach(function (to, from, next) {
  if(to.meta.requireAuth){
    // 要去的url只有登陆成功后才能访问
    if (store.state.token) {
      next()
    } else {
      next({name: 'login',query: {backUrl: to.fullPath}})
    }
  }else{
    next()
  }
});

4、登录组件

1、向后端发送post登录请求;

this.$axios.request({
  url:'http://127.0.0.1:8002/api/login/',
  method:"POST",
  data:{
    user:that.username,
    pwd:that.password
  },
  headers:{'Content-Type':'application/json',
  },

2、后端对请求的用户名和密码进行验证,若通过返回{code:1000,token='1212'}信息,反之返回错误信息{code:1001,error:'asas'}

3、前段收到返回的信息后,若code为1000,则说明验证通过,将用户名和token通过vue存入cookie中以便持久化;

4、登录成功后跳转至index\或者对于的页面;

完整代码:

<script>
  import ElRow from "element-ui/packages/row/src/row";
    export default {
      components: {ElRow},
      name: "Login",
      data(){
          return{
            username:'',
            password:'',
          }
      },
      methods:{
         onSubmit:function () {
            var that = this;
            this.$axios.request({
              url:'http://127.0.0.1:8002/api/login/',
              method:"POST",
              data:{
                user:that.username,
                pwd:that.password
              },
              headers:{
//                'Content-Type':'application/json',
              },
            }).then(function (response) {
                console.log(response.data);
                
                if(response.data.code===1000){
                    that.$store.commit('saveToken',{token:response.data.token,username:that.username});
                    var url = that.$route.query.backUrl;
                    console.log('url>>>>',url);
                    if(url){
                      that.$router.push({path:url})
                    }else{
                      that.$router.push({name:'index'})
                    }
                }
                else {
                    alert(response.data.error);
                    that.username='';
                    that.password='';
                }
            }).catch(function (response) {
            })
         }
      }
    }
</script>

5、课程页面组件

注意api接口必须携带正确的token,否则django后台会验证失败!

<script>
    export default {
      name: "courses",
      data(){
        return{
          courses:[]
        }
      },

      mounted(){
        this.initCourseList()
      },

      methods:{
        initCourseList:function () {
          var that = this;
          this.$axios.request({
            url:'http://127.0.0.1:8002/api/courses/',
            method:"GET",
            
            // 发送token参数到后端进行验证
            params:{
                token:that.$store.state.token,
            }
          }).then(function (response) {
            console.log(response);
            that.courses=response.data.data
          })
        }
      }
    }
</script>

App.vue

1、登录后则切换为用户名,反之则显示登录;

2、

<template>
  <div id="app">
    <el-container>
       <el-header>
         <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal"
                  @select="handleSelect" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
           <el-menu-item index="1"><router-link to="/index">首页</router-link></el-menu-item>
           <el-menu-item index="2"><router-link to="/courses">课程列表页</router-link></el-menu-item>

           <el-menu-item index="2">
             <!--从全局取出存在在cookie中的用户名,若未登录则直接显示登录-->
             <span v-if="this.$store.state.token">{{this.$store.state.username}}</span>
             <span v-else="">
               <router-link to="/login">登录</router-link>
             </span>
           </el-menu-item>

           <el-menu-item index="4"><span v-on:click="logout">退出</span></el-menu-item>
         </el-menu>

      </el-header>

      <keep-alive>
         <el-main>
           <router-view/>
         </el-main>
    </keep-alive>

    </el-container>
    </div>
</template>

<script>
  import ElContainer from "../node_modules/element-ui/packages/container/src/main";
  export default {
    components: {ElContainer},
    name: 'App',
    data(){
        return{
          activeIndex: '1',
          activeIndex2: '1',
        }
    },

    methods:{
      handleSelect:function () {
        },
      logout:function () {
        this.$store.commit('clearToken')
        this.$router.push({name:'login'})
      }
    }
  }
</script>

django后端

urls

from django.conf.urls import url
from .views import CourseView, LoginView


urlpatterns = [
    url(r'^courses/$', CourseView.as_view()),
    url(r'^login/$', LoginView.as_view()),
    url(r'^courses/(?P<pk>\d+)/$', CourseView.as_view()),
]

views

from django.shortcuts import render
import uuid
from app1.auth.auth import TokenAuth


class CourseSerializer(serializers.ModelSerializer):
    # 若存在连表查询,可以直接在此处使用
    degree = serializers.CharField(source='get_degree_display')
    teacher = serializers.CharField(source='teacher.name')
    chapters = serializers.SerializerMethodField()
    class Meta:
        model = Course
        fields = '__all__'

    def get_chapters(self,obj):
        query_set = obj.chapter_set.all()
        return [{'title':item.name,'url':item.url} for item in query_set]


class CourseView(APIView):
    authentication_classes = [TokenAuth,]
    def get(self, request, *args, **kwargs):
        self.dispatch
        pk = kwargs.get('pk', '')
        ret = {'code':1000, 'data':None}
        try:
            if pk:
                course_obj = Course.objects.filter(id=pk).first()
                ser = CourseSerializer(instance=course_obj,many=False)
            else:
                course_list = Course.objects.all()
                ser = CourseSerializer(instance=course_list, many=True)

            ret['data'] = ser.data
        except Exception as e:
            print(e)
            ret['code']=1001
            ret['error'] = '获取课程失败'
        print(ret)
        return Response(ret)
        
    
class LoginView(APIView):
    def post(self, request, *args, **kwargs):
        ret = {'code': 1000}
        user = request.data.get('user','')
        pwd = request.data.get('pwd','')
        user_obj = UserInfo.objects.filter(username=user,password=pwd).first()
        if not user_obj:
            ret['code'] = 1001
            ret['error'] = "用户名或密码错误"
        else:
            token = str(uuid.uuid4())
            Token.objects.update_or_create(user_id=user_obj.id,defaults={'token':token})
            ret['token']= token
        return Response(ret)

自定义认证组件

验证token是否合法,若不合法直接抛出异常,合法则通过。

# auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed


class TokenAuth(BaseAuthentication):
    """自定义验证类"""

    def authenticate(self, request):
        """验证逻辑"""
        token = request._request.GET.get('token', '')
        print('token>>>>>>>',token)
        token_obj = Token.objects.filter(token=token).first()

        # 验证失败
        if not token_obj:
            raise AuthenticationFailed('认证失败')

        # 通过验证
        return (token_obj.user, token_obj)

    def authenticate_header(self, request):
        pass
        

猜你喜欢

转载自www.cnblogs.com/fqh202/p/9662690.html
今日推荐