一.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. C# Winform 学习(四)

    目标 1.文本类 2.选择类 3.导航类 一.文本类控件 1.文本标签Label 1)命名:lbl开始 2)常用属性: Text.Visible 2.文本框TextBox 1)命名:txt开始 2)常 ...

  2. Java实现 LeetCode 112 路径总和

    112. 路径总和 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和. 说明: 叶子节点是指没有子节点的节点. 示例: 给定如下二叉树,以及目标 ...

  3. Android如何使用OKHttp

    首先要在build.gradle里面写入 // 添加OKHttp支持 implementation("com.squareup.okhttp3:okhttp:4.3.1") 下面是 ...

  4. java实现和为定值的两个数

    1 问题描述 输入一个整数数组和一个整数,在数组中查找两个数,满足他们的和正好是输入的那个整数.如果有多对数的和等于输入的整数,输出任意一对即可.例如,如果输入数组[1,2,4,5,7,11,15]和 ...

  5. Java实现 洛谷 P1149 火柴棒等式

    import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.S ...

  6. java实现第39级台阶(三十九级台阶)

    标题: 第39级台阶 小明刚刚看完电影<第39级台阶>,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级! 站在台阶前,他突然又想着一个问题: 如果我每一步只能迈上1个或2个台阶.先 ...

  7. redis基础知识详解

    一.redis基础知识 1.Redis是什么Redis是一个开源的key-value存储系统. 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表 ...

  8. [原创][开源] SunnyUI.Net 主题

    SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...

  9. Postgresql DB安装和使用问题记录

    2.选择语言后提示: Error: There has been an error. Please put SELinux in permissive mode and then run instal ...

  10. pip install 执行过程中遇到的各种问题

    一.pip install 安装指定版本的包 要用 pip 安装指定版本的 Python 包,只需通过 == 操作符 指定. pip install robotframework == 2.8.7 将 ...