一.token:

铺垫:  

之前用的是通过最基本的用户名密码登录我的运维平台http://127.0.0.1:8000/---这种用的是form表单,但是这种对于前后端分离的不适合。前后端分离,应该通过http的url地址去登录,登录完之后获取一个token,我下次请求只需要带着这个token去获取数据即可。

查看django-drf认证官方配置:

如下图中可以看到它中有几个认证方式,它默认的认证是BasicAuthentication和SessionAuthentication认证。

1.默认的认证就走的session认证,只要前后端没有分离的情况下,所有认证全部走的session,也就是你登录完后,后端会向你的浏览器cookie中写入一数据,此数据代表了你的身份。但这个数据它实际上跟session有一定的关联,如下进它的数据库查看session表:

当用户登录之后发现有如下一条记录,而session_key是放在浏览器上的,session_data就是它的value,这种方式就是session认证。

如下图:session_key就是在浏览器的application下的cookie中---sessionid:

这是最原始的方式,通过session登录。!

2.django-drf默认用session和basic,这两个默认我们要写上,如果不想用默认的session,那把session关掉即可那就用用户名登录不了了,那怎样配置,怎样知道它默认用session登录?如下图,它的官方配置默认就支持session和basic,所以如果我想用别的方式就把这个代码配置拷贝到我项目settings.py中的drf中,并覆盖掉它默认值即可--建议线上把session关掉,basic留着:

token:

  经查看它的源码authentication.py中可知它有提供TokenAuthentication方法(上图1中有),所以我把此方法复制并配置到我项目settings.py中即可如下:

1.配置token:

REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
'PAGE_SIZE':10,
'DEFAULT_PAGINATION_CLASS':'users.pagination.Pagination',
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
# 'devops.permissions.Permissions',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', <<<这里我配置同时支持session和token
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'

],

}

2.配置installed_apps:

  就像上述所说的,如果用session的话,数据库中有session表,那使用token它也有一张表,我要想同步表结构,必须要把token放在installed_app中,

.....
'rest_framework.authtoken',
'rest_framework',
.....

3.同步数据库:

(python36env) [vagrant@CentOS devops]$ python manage.py makemigrations

(python36env) [vagrant@CentOS devops]$ python manage.py migrate

(python36env) [vagrant@CentOS devops]$ python manage.py dbshell

MariaDB [devops]> show tables;如下已经有token表了

authtoken_token

4.配置url地址:在项目urls.py中加入如下代码:

from rest_framework.authtoken import views
urlpatterns += [
url(r'^api-token-auth/', views.obtain_auth_token)
]

(python36env) [vagrant@CentOS devops]$ python manage.py runserver 0.0.00:8000启动服务

5.测试:用curl命令用户登录,要先登录所以走的是post,-d参数走json数据,-H告诉它用json去解析

(python36env) [vagrant@CentOS devops]$ curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"123456"}' http://127.0.0.1:8000/api-token-auth/

结果如下拿到token了
{"token":"780ba1a240a974b958731bb446c5a7574976df4e"}

去数据库看如下,也有了,告诉我们创建时间created,但是发现没有过期时间,也就是说申请了这个token,我再次去请求,拿到的还是这个token,永远不过期。那怎样让它过期,手动删除此token即可。

MariaDB [devops]> select * from authtoken_token\G;
key: 780ba1a240a974b958731bb446c5a7574976df4e
created: 2020-06-26 15:00:56.118433
user_id: 2

6.获取数据:

(1)给我的运维平台所有api加上访问权限--批量配置(只要登录就可访问):

settings.py:

REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
'PAGE_SIZE':10,
'DEFAULT_PAGINATION_CLASS':'users.pagination.Pagination',
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
'DEFAULT_PERMISSION_CLASSES': [
# 'rest_framework.permissions.AllowAny',
'devops.permissions.Permissions', <<<<打开模型权限,此时所有的api就需要登录权限
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
}

(2)怎样使用我上述拿到的token去访问数据:

(python36env) [vagrant@CentOS devops]$ curl -X GET http://127.0.0.1:8000/users/
{"detail":"Authentication credentials were not provided."} <<<<它告诉我需要权限,如下我加上我的token后就拿到数据了
(python36env) [vagrant@CentOS devops]$ curl -X GET http://127.0.0.1:8000/users/ -H 'Authorization: Token 780ba1a240a974b958731bb446c5a7574976df4e'
{"count":98,"next":"http://127.0.0.1:8000/users/?page=2","previous":null,"results":[{"id":1,"username":"devops","email":"123@qq.com"}...
格式化一下如下:就显示标准json结果了
(python36env) [vagrant@CentOS devops]$ curl -X GET http://127.0.0.1:8000/users/ -H 'Authorization: Token 780ba1a240a974b958731bb446c5a7574976df4e'|python -m json.tool
{
"count": 98,
"next": "http://127.0.0.1:8000/users/?page=2",
"previous": null,
"results": [
{
"id": 1,
"username": "devops",
"email": "123@qq.com"
},
{
"id": 2,
"username": "admin",
"email": "admin@51reboot.com"
},
.........

  拿到的token永远不过期,要使过期就手动删除它。因为表中token直接跟user_id关联上,跟某user_id关联上就代表此用户已经登录了,如果这个用户是超级管理员,你只要拿到这个token,那所有的权限信息你也会拥有,那这样就很危险了,因为它永远不过期,不变。除非你每天晚上刷一次,把token表清空。

二.jwt

前后端分离之JWT用户认证https://www.jianshu.com/p/180a870a308a

参考https://github.com/jpadilla/django-rest-framework-jwt

(python36env) [vagrant@CentOS devops]$ pip install djangorestframework-jwt  安装

1.配置权限验证--我这里是基于模型的

REST_FRAMEWORK = {
.....
'DEFAULT_PERMISSION_CLASSES': [
# 'rest_framework.permissions.AllowAny',
'devops.permissions.Permissions',
],
......

2.配置认证后端类

REST_FRAMEWORK = {
.....
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
...

3.配置url---devops/urls.py:

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
url(r'^', include(route.urls)),
url(r'^aip-auth', include("rest_framework.urls",namespace="reset_framework")),
url(r'^docs/', include_docs_urls("lizhihua运维平台接口文档")),
url(r'^api-token-auth/', obtain_jwt_token)
]

(python36env) [vagrant@CentOS devops]$ python manage.py runserver 0.0.00:8000启动服务

4.测试:

(python36env) [vagrant@CentOS devops]$ curl -X POST -d "username=admin&password=123456" http://localhost:8000/api-token-auth/   拿到token
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTkzMjI0NDI2LCJlbWFpbCI6ImFkbWluQDUxcmVib290LmNvbSJ9.SZhNkN6WgkKyMEZKora7rZRzHgbMQyTRrFP7OFxg0Ts"}

5.获取数据

(python36env) [vagrant@CentOS devops]$ curl -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTkzMjI0MzU1LCJlbWFpbCI6ImFkbWluQDUxcmVib290LmNvbSJ9.3cn__Tc3ddUhl4_PhST83vRZBcNASs0UBKdLvhgupt4" http://localhost:8000/users/|python -m json.tool

{
"count": 98,
"next": "http://localhost:8000/users/?page=2",
"previous": null,
"results": [
{
"id": 1,
"username": "devops",
"email": "123@qq.com"
},
{
"id": 2,
"username": "admin",
"email": "admin@51reboot.com"
},
.....

jwt默认它的过期时间是300s,如果想改的话在项目settings.py中如下位置drf下改即可:

import datetime
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3000), <<<<秒
}

三.前端框架

参考https://juejin.im/post/59097cd7a22b9d0065fb61d2

1.需要在windows装node环境----https://nodejs.org/en/下载想要的版本即可

C:\Users\Administrator>node -v
v12.18.1

2.git clone 想要的vue模版并npm run dev

3.修改项目主题---vueAdmin-template/index.html中修改title

4.配置用户登录

(1)登录页面配置src/views/login/index.vue

<template>
<div class="login-container">
<el-form autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left" label-width="0px"
class="card-box login-form">
<h3 class="title">lizhihua运维平台</h3>
<el-form-item prop="username">
<span class="svg-container svg-container_login">
<svg-icon icon-class="user" />
</span>
<el-input type="text" v-model="loginForm.username" autoComplete="off" placeholder="请输入用户名" />
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password"></svg-icon>
</span>
<el-input :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="off"
placeholder="请输入密码"></el-input>
<span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" /></span>
</el-form-item>
<el-form-item>
<el-button type="primary" style="width:100%;" :loading="loading" @click.native.prevent="handleLogin">
登录
</el-button>
</el-form-item>
</el-form>
</div>
</template> <script>
// import { isvalidUsername } from '@/utils/validate'
export default {
name: 'login',
data() {
return {
loginForm: {
username: '',
password: ''
},
loginRules: {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
},
loading: false,
pwdType: 'password'
}
},
methods: {
showPwd() {
if (this.pwdType === 'password') {
this.pwdType = ''
} else {
this.pwdType = 'password'
}
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('Login', this.loginForm).then(() => {
this.loading = false
this.$router.push({ path: '/' })
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
}
}
</script> <style rel="stylesheet/scss" lang="scss">
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee; .login-container {
position: fixed;
height: 100%;
width:100%;
background-color: $bg;
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px #293444 inset !important;
-webkit-text-fill-color: #fff !important;
}
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
}
.el-input {
display: inline-block;
height: 47px;
width: 85%;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
&_login {
font-size: 20px;
}
}
.title {
font-size: 26px;
font-weight: 400;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
.login-form {
position: absolute;
left: 0;
right: 0;
width: 400px;
padding: 35px 35px 15px 35px;
margin: 120px auto;
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select:none;
}
.thirdparty-button{
position: absolute;
right: 35px;
bottom: 28px;
}
}
</style>

(3)config/dev.env.js

module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
BASE_API: '"http://127.0.0.1:8000"',
})

(4)src/api/login.js

export function login(username, password) {
return request({
url: '/api-token-auth/',
method: 'post',
data: {
username,
password
}
})
}

F:\devops\data\web\vueAdmin-template>npm run dev    重启服务

(5)src/utils/request.js:修改配置request拦截器

 配置成每次请求把token带上,这里用jwt

import axios from 'axios'
import { Message } from 'element-ui'
import store from '../store'
import { getToken } from '@/utils/auth' // 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
timeout: 5000 // 请求超时时间
}) // request拦截器
service.interceptors.request.use(config => {
if (store.getters.token) {
config.headers['Authorization'] = 'JWT ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}) // respone拦截器
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
console.log(response)
return response.data
},
error => {
console.log('err' + error)
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
) export default service

(6)src/store/modules/user.js:  配置把token写到浏览器cookie中

.....
actions: {
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
setToken(response.token)
commit('SET_TOKEN', response.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
........

(7)src/utils/auth.js:

....
const TokenKey = 'Token'
....

(8)src/permission.js: 配置登录成功则跳转到首页

import router from './router'
import store from './store'
import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css'// Progress 进度条样式
import { Message } from 'element-ui'
import { getToken } from '@/utils/auth' // 验权 const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.name === '') {
store.dispatch('GetInfo').then(res => { // 拉取用户信息
next({ ...to, replace: true })
}).catch((err) => {
store.dispatch('FedLogOut').then(() => {
Message.error(err || 'Verification failed, please login again')
next({ path: '/' })
})
})
} else {
next()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
NProgress.done()
}
}
}) router.afterEach(() => {
NProgress.done() // 结束Progress
})

(9)src/views/dashboad/index.vue :

<template>
<div class="dashboard-container">
dashboard
</div>
</template> <script>
export default {
name: 'dashboard'
}
</script>

这样就能登录后跳转到首页了!

若登录后跳转并如下报错:原因是没获取到userinfo对象

GET http://127.0.0.1:8000/UserInfo/ 404 (Not Found)
[Vue warn]: data functions should return an object:

解决:导入userinfo即可

from django.conf.urls import url, include
from django.contrib import admin
from rest_framework.routers import DefaultRouter
from rest_framework.documentation import include_docs_urls
from rest_framework_jwt.views import obtain_jwt_token
from idcs.views import IdcViewset
from users.views import UserViewset, DashboardStatusViewset, UserInfoViewset
from cabinet.views import CabinetViewset
from manufacturer.views import ManufacturerViewset, ProductModelViewset
from servers.views import ServerAutoReportViewset, NetworkDeviceViewset, IPViewset, ServerViewset route = DefaultRouter()
route.register("idcs", IdcViewset, basename="idcs")
route.register("users", UserViewset, basename="users")
route.register("UserInfo", UserInfoViewset, basename="UserInfo")
route.register("cabinet", CabinetViewset, basename="cabinet")
route.register("Manufacturer", ManufacturerViewset, basename="Manufacturer")
route.register("ProductModel", ProductModelViewset, basename="ProductModel")
route.register("ServerAutoReport", ServerAutoReportViewset, basename="ServerAutoReport")
route.register("Servers", ServerViewset, basename="Servers")
route.register("NetworkDevice", NetworkDeviceViewset, basename="NetworkDevice")
route.register("IP", IPViewset, basename="IP")
route.register("dashboardStatus", DashboardStatusViewset, basename="dashboardStatus") urlpatterns = [
url(r'^', include(route.urls)),
url(r'^api-auth', include("rest_framework.urls", namespace="rest_framework")),
url(r'^docs/', include_docs_urls("51reboot运维平台接口文档")),
url(r'^api-token-auth/', obtain_jwt_token),
]

11

22

二.3.token认证,jwt认证,前端框架的更多相关文章

  1. drf框架 - JWT认证插件

    JWT认证 JWT认证方式与其他认证方式对比: 优点 1) 服务器不要存储token,token交给每一个客户端自己存储,服务器压力小 2)服务器存储的是 签发和校验token 两段算法,签发认证的效 ...

  2. 跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证

    Go gRPC 系列: 跟我一起学Go系列:gRPC安全认证机制-SSL/TLS认证 跟我一起学 Go 系列:gRPC 拦截器使用 跟我一起学 Go 系列:gRPC 入门必备 接上一篇继续讲 gRPC ...

  3. Json Web Token(JWT)

    Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(Si ...

  4. ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新

    来源:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_26.html 本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及T ...

  5. drf框架中jwt认证,以及自定义jwt认证

    0909自我总结 drf框架中jwt 一.模块的安装 官方:http://getblimp.github.io/django-rest-framework-jwt/ 他是个第三方的开源项目 安装:pi ...

  6. jwt认证生成后的token如何传回后端并解析的详解

    jwt认证生成后的token后端解析 一.首先前端发送token token所在的位置headers {'authorization':token的值',Content-Type':applicati ...

  7. drf认证组件、权限组件、jwt认证、签发、jwt框架使用

    目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...

  8. drf认证组件(介绍)、权限组件(介绍)、jwt认证、签发、jwt框架使用

    目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...

  9. Dotnet core使用JWT认证授权最佳实践(二)

    最近,团队的小伙伴们在做项目时,需要用到JWT认证.遂根据自己的经验,整理成了这篇文章,用来帮助理清JWT认证的原理和代码编写操作. 第一部分:Dotnet core使用JWT认证授权最佳实践(一) ...

随机推荐

  1. Java实现蓝桥杯基础练习特殊回文数

    基础练习 特殊回文数 时间限制:1.0s 内存限制:512.0MB 提交此题 锦囊1 锦囊2 问题描述 123321是一个非常特殊的数,它从左边读和从右边读是一样的. 输入一个正整数n, 编程求所有这 ...

  2. Java实现 蓝桥杯VIP 算法提高 超级玛丽

    算法提高 超级玛丽 时间限制:1.0s 内存限制:256.0MB 问题描述 大家都知道"超级玛丽"是一个很善于跳跃的探险家,他的拿手好戏是跳跃,但它一次只能向前跳一步或两步.有一次 ...

  3. Java实现 计蒜客 1251 仙岛求药

    仙岛求药 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处.迷阵由 M \times NM× ...

  4. 第五届蓝桥杯JavaA组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.猜年龄 题目描述 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍" ...

  5. java实现第六届蓝桥杯九数组分数

    九数组分数 九数组分数 1,2,3...9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码. public class A { public s ...

  6. PAT 有理数四则运算

    本题要求编写程序,计算 2 个有理数的和.差.积.商. 输入格式: 输入在一行中按照 a1/b1 a2/b2 的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只可能出现在分子前 ...

  7. java关键字final用法详解

    final关键字在java中也是属于比较常用的一种,因此也算得上是一个比较重要的关键字,有必要对它进行深入的学习. 一.定义:用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成 ...

  8. python基础:如何使用 pip 安装第三方库

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 在这个生活中处处都是大数据和人工智能的时代,总是能在各种角落看到 Pyth ...

  9. IAT表

    0X0 0 DLL介绍 DLL翻译器为动态链接库,原来不存在DLL的概念只有,库的概念,编译器会把从库中获取的二进制代码插入到应用程序中.在现在windows操作系统使用了数量庞大的库函数(进程,内存 ...

  10. Spark原始码系列(五)分布式缓存

    问题导读:spark缓存是如何实现的?BlockManager与BlockManagerMaster的关系是什么? 这个persist方法是在RDD里面的,所以我们直接打开RDD这个类. def pe ...