vue前端
1、安装vuex和vue-cookie
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');
}
}
})
3、引入vuex和vue-cookie
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