一.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实现 LeetCode 486 预测赢家

    486. 预测赢家 给定一个表示分数的非负整数数组. 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,--.每次一个玩家只能拿取一个分数,分数被拿取之后不再可 ...

  2. Java实现 LeetCode 222 完全二叉树的节点个数

    222. 完全二叉树的节点个数 给出一个完全二叉树,求出该树的节点个数. 说明: 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集 ...

  3. java实现数字的值返回

    以下的静态方法实现了:把串 s 中第一个出现的数字的值返回. 如果找不到数字,返回-1 例如: s = "abc24us43" 则返回 2 s = "82445adb5& ...

  4. Linux 权限管理-ACL权限

    ACL权限是为了在现有的所有者.所属组.其他人不够使用的情况下使用的,使用它必须保证文件所在的分区支持ACL df -h:查看系统所有分区信息 dumpe2fs -h /dev/vda1,可以查看分区 ...

  5. mysql安装过程以及遇到问题的解决方法

    因为工作原因,配备了新电脑,需要装mysql,今天给大家分享一下安装的过程以及遇到的问题(在此仅介绍压缩包解压方式的安装) 1.准备mysql的压缩包(我使用的是5.7经典版本) 2.配置环境变量,这 ...

  6. 如何向这些CA来申请数字证书呢?

    申请的过程大致是: 1.自己本地先生成一对密匙,然后拿着自己的公匙以及其他信息(比如说企业名称啊什么的)去CA申请数字证书. 2.CA在拿到这些信息后,会选择一种单向Hash算法(比如说常见的MD5) ...

  7. 如何修改centOS7的GUI图形界面

    在安装Gnome包之前,需要检查一下安装源(yum)是否正常,因为需要在yum命令来安装gnome包. 第一步:先检查yum 是否安装了,以及网络是否有网络.如果这两者都没有,先解决网络,在解决yum ...

  8. Centos7 安装 redis6 的部分问题总结

    首先把redis.tar.gz 解压到你想要的路径 检查一下安装环境: yum -y install gcc yum -y install epel-release 执行 make 和 make in ...

  9. 关键时刻,让你的iphone拒绝掉的所有来电

    夜间被骚扰电话吵醒是会非常烦躁的,以下就是iphone的勿扰模式,配合刚出的夜间深夜模式非常的nice. 可以自定义设置时间段,每天智能切换. 也可以开启个人收藏的白名单,让家人有紧急事情也可以联系到 ...

  10. Iterable对象

    ''' 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器和带yield的ge ...