二.3.token认证,jwt认证,前端框架
一.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认证,前端框架的更多相关文章
- drf框架 - JWT认证插件
JWT认证 JWT认证方式与其他认证方式对比: 优点 1) 服务器不要存储token,token交给每一个客户端自己存储,服务器压力小 2)服务器存储的是 签发和校验token 两段算法,签发认证的效 ...
- 跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证
Go gRPC 系列: 跟我一起学Go系列:gRPC安全认证机制-SSL/TLS认证 跟我一起学 Go 系列:gRPC 拦截器使用 跟我一起学 Go 系列:gRPC 入门必备 接上一篇继续讲 gRPC ...
- Json Web Token(JWT)
Json web token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(Si ...
- ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新
来源:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_26.html 本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及T ...
- drf框架中jwt认证,以及自定义jwt认证
0909自我总结 drf框架中jwt 一.模块的安装 官方:http://getblimp.github.io/django-rest-framework-jwt/ 他是个第三方的开源项目 安装:pi ...
- jwt认证生成后的token如何传回后端并解析的详解
jwt认证生成后的token后端解析 一.首先前端发送token token所在的位置headers {'authorization':token的值',Content-Type':applicati ...
- drf认证组件、权限组件、jwt认证、签发、jwt框架使用
目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...
- drf认证组件(介绍)、权限组件(介绍)、jwt认证、签发、jwt框架使用
目录 一.注册接口 urls.py views.py serializers.py 二.登录接口 三.用户中心接口(权限校验) urls.py views.py serializers.py 四.图书 ...
- Dotnet core使用JWT认证授权最佳实践(二)
最近,团队的小伙伴们在做项目时,需要用到JWT认证.遂根据自己的经验,整理成了这篇文章,用来帮助理清JWT认证的原理和代码编写操作. 第一部分:Dotnet core使用JWT认证授权最佳实践(一) ...
随机推荐
- C# Winform 学习(四)
目标 1.文本类 2.选择类 3.导航类 一.文本类控件 1.文本标签Label 1)命名:lbl开始 2)常用属性: Text.Visible 2.文本框TextBox 1)命名:txt开始 2)常 ...
- Java实现 LeetCode 112 路径总和
112. 路径总和 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和. 说明: 叶子节点是指没有子节点的节点. 示例: 给定如下二叉树,以及目标 ...
- Android如何使用OKHttp
首先要在build.gradle里面写入 // 添加OKHttp支持 implementation("com.squareup.okhttp3:okhttp:4.3.1") 下面是 ...
- java实现和为定值的两个数
1 问题描述 输入一个整数数组和一个整数,在数组中查找两个数,满足他们的和正好是输入的那个整数.如果有多对数的和等于输入的整数,输出任意一对即可.例如,如果输入数组[1,2,4,5,7,11,15]和 ...
- Java实现 洛谷 P1149 火柴棒等式
import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.S ...
- java实现第39级台阶(三十九级台阶)
标题: 第39级台阶 小明刚刚看完电影<第39级台阶>,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级! 站在台阶前,他突然又想着一个问题: 如果我每一步只能迈上1个或2个台阶.先 ...
- redis基础知识详解
一.redis基础知识 1.Redis是什么Redis是一个开源的key-value存储系统. 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表 ...
- [原创][开源] SunnyUI.Net 主题
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- Postgresql DB安装和使用问题记录
2.选择语言后提示: Error: There has been an error. Please put SELinux in permissive mode and then run instal ...
- pip install 执行过程中遇到的各种问题
一.pip install 安装指定版本的包 要用 pip 安装指定版本的 Python 包,只需通过 == 操作符 指定. pip install robotframework == 2.8.7 将 ...