技术分享网

08-07 资讯 投稿:塔安琪
conn = ssl.create_connection((hostname, port)) context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) sock = context.wrap_socket(conn, server_hostname=hostname) cert = ssl.DER_cert_to_PEM_cert(sock.getpeercert(True)) x509 = OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_PEM, cert) start_date = str(x509.get_notBefore(), encoding= utf-8 ) expire_date = str(x509.get_notAfter(), encoding= utf-8 ) # time 字符串转时间数组 start_date = datetime.strptime(start_date, %Y%m%d%H%M%SZ ) # datetime 字符串转时间数组 expire_date = datetime.strptime(expire_date, %Y%m%d%H%M%SZ ) # 剩余天数 remain_days = (expire_date-datetime.now()).days print( {} ssl start_date,expire_date,remain_days is {},{},{} .format( domain, start_date, expire_date, remain_days)) return start_date, expire_date, remain_days except Exception as e: print( {} {} .format(e.__traceback__.tb_lineno, e)) return datetime.now(), datetime.now(), -999999999if __name__ == __main__ : remain_days = main( www.guojingyi.cn ) print(remain_days) shell将多行内容的换行符替换为指定字符,然后进行拼接
grep ^pt_key ../env/all_cookies.txt | paste -s -d 
也可以使用tr进行替换,但是拼接末尾会多出指定字符,需要额外处理

卸载双系统中的linuxwindows中cmd以管理员身份运行——执行命令“bcdboot C:\Windows” (假设c 盘位系统盘,请根据实际情况操作)——重启只有windows了

首选确认该efi分区跟windows不是同一个efi分区(防止毁了windows正常启动)

win+r执行命令diskpart

Microsoft DiskPart 版本 10.0.19041.964Copyright (C) Microsoft Corporation.在计算机上: DESKTOP-VN503BDDISKPART> list disk 磁盘 ### 状态 大小 可用 Dyn Gpt -------- ------------- ------- ------- --- --- 磁盘 0 联机 223 GB 1024 KB * 磁盘 1 联机 111 GB 1024 KB * 磁盘 2 联机 465 GB 465 GB * 磁盘 3 联机 931 GB 2048 KB *DISKPART> select disk 2磁盘 2 现在是所选磁盘。DISKPART> list partition 分区 ### 类型 大小 偏移量 ------------- ---------------- ------- ------- 分区 1 系统 300 MB 1024 KBDISKPART> select partition 1分区 1 现在是所选分区。DISKPART> delete partition overrideDiskPart 成功地删除了所选分区。DISKPART>

打开windows的磁盘管理,发现该linux所在硬盘,全部分区、空间可操作使用了。

simplejwt token前后端验证详解

前后端分离场景:

django

djangorestframework

djangorestframework-simplejwt

element-ui

范例说明:

后端部分代码:

serializers.py

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer# Custom Token ObtainPairSerializerclass CustomTokenObtainPairSerializer(TokenObtainPairSerializer): 自定义jwt认证返回值 def validate(self, attrs): data = super().validate(attrs) refresh = self.get_token(self.user) data['refresh'] = str(refresh) data['access'] = str(refresh.access_token) data['user_id'] = self.user.id data['user_name'] = self.user.username return data

views.py

from backend.serializers import *from rest_framework_simplejwt.views import TokenObtainPairView# custom token viewclass CustomTokenObtainPairView(TokenObtainPairView): serializer_class = CustomTokenObtainPairSerializer

urls.py

from django.contrib import adminfrom django.views.generic import TemplateViewfrom django.urls import path, includefrom rest_framework_simplejwt.views import TokenRefreshView, TokenVerifyViewfrom rest_framework.routers import DefaultRouterfrom backend import viewsrouter = DefaultRouter()router.register(r'users', views.UserViewSet)router.register(r'groups', views.GroupViewSet)# 使用自动url路由连接我们的API# 另外,我们还包括支持浏览器浏览API的登录URLapp_name = 'backend'urlpatterns = [ path('', TemplateView.as_view(template_name='index.html'), name='index'), path('admin/', admin.site.urls), # django 管理员视图 path('alterpassword/', views.AlterPassword.as_view()), path('search/', views.GlobalSearchAPIView.as_view(), name= search ), path('api/ version /', include(router.urls)), # 自定义rest api path('api-token-auth/', views.CustomTokenObtainPairView.as_view(), name='custom_token_obtain_pair'), # rest_framework_simplejwt 生成 path('api-token-refresh/', TokenRefreshView.as_view(), name='token_refresh'), # rest_framework_simplejwt 刷新 path('api-token-verify/', TokenVerifyView.as_view(), name='token_verify'), # rest_framework_simplejwt 验证 path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), # rest framework api 可视化]

前端部分代码:

axios-filter.js(拦截器)

import axios from 'axios'import { Message } from 'element-ui'import router from '@/router'// 读取cookie中的csrftokenaxios.defaults.xsrfCookieName = 'csrftoken'// axios header设置X-CSRFTOKENaxios.defaults.xsrfHeaderName = 'X-CSRFTOKEN'// 设置Content-Typeaxios.defaults.headers = { 'Content-Type': 'application/json;charset=UTF-8'// 设置超时时间axios.defaults.timeout = 50000// request拦截器axios.interceptors.request.use( config = { // sessionStorage 如果存在jwt token if (sessionStorage.token) { // 则JWT token认证格式,写入header config.headers.Authorization = 'JWt ' + sessionStorage.token // console.log(sessionStorage.token) return config error = { // console.log(error) return Promise.reject(error)// reponse自定义拦截器 startfunction customAxiosResponseInterceptor () { const interceptor = axios.interceptors.response.use( response = response, error = { // console.log(error) var config = error.config if (error.response.status === 401) { axios.interceptors.response.eject(interceptor) let data = { 'refresh': sessionStorage.getItem('refresh') } return axios.post('/api-token-refresh/', data).then(response = { sessionStorage.setItem('token', response.data.access) console.log('refresh access token success') // 重新发送请求 return axios(config) }).catch(error = { Message({ showClose: true, message: '登录超时,请重新登录!!!', type: 'error' redirectLoginWithQuery() console.log(error) return Promise.reject(error) }).finally(customAxiosResponseInterceptor) } else { Message({ showClose: true, message: error.response.data, type: 'error' return Promise.reject(error)customAxiosResponseInterceptor()// reponse自定义拦截器 end// login with redirectfunction redirectLoginWithQuery () { router.push({ path: '/login', query: { redirect: router.currentRoute.fullPathexport default axios

login.vue

 template  el-form @keyup.enter.native= submitForm('loginForm')  :model= loginForm  status-icon :rules= rules  ref= loginForm  label-width= 55px  'loginForm')  登录 /el-button  el-button @click= resetForm('loginForm') 重置 /el-button  /el-form-item  /el-form  /template  script export default { data () { var validateName = (rule, value, callback) = { if (!value) { callback(new Error('请输入用户名')) } else { callback() var validatePass = (rule, value, callback) = { if (!value) { callback(new Error('请输入密码')) } else { callback() return { checked: false, loginForm: { name: '', pass: '' rules: { name: [ { validator: validateName, trigger: 'blur' } pass: [ { validator: validatePass, trigger: 'blur' } loading: false methods: { submitForm (formName) { this.$refs[formName].validate((valid) = { if (valid) { var that = this this.$refs.button_login.loading = true this.$axios.request( // 发送axios请求 url: '/api-token-auth/', // 请求路径 method: 'POST', // 请求方式 data: { // 要发送的数据 username: this.loginForm.name, password: this.loginForm.pass responseType: 'json' // 期望返回的类型是json格式 ).then(response = { // 把返回的结果交给回调函数处理 console.log(response) sessionStorage.setItem('token', response.data.access) sessionStorage.setItem('refresh', response.data.refresh) sessionStorage.setItem('user_id', response.data.user_id) sessionStorage.setItem('user_name', response.data.user_name) this.$message.success('登录成功') let redirect = decodeURIComponent(this.$route.query.redirect || '/') that.$router.push({ path: redirect }) // console.log(sessionStorage) }).catch(error = { this.$message.error(error) console.log(error) this.$refs.button_login.loading = false } else { console.log('请输入合法用户名和密码') this.$message.error('请输入合法用户名和密码') return false resetForm (formName) { this.$refs[formName].resetFields() keyupEnter () { const that = this if (window.event.keyCode === 13) { that.submitForm('loginForm') mounted () { window.addEventListener('keyup', this.keyupEnter, false) beforeDestroy () { window.removeEventListener('keyup', this.keyupEnter, false) /script  style lang= scss scoped .login-container { -webkit-border-radius: 5px; border-radius: 5px; -moz-border-radius: 5px; background-clip: padding-box; margin: 180px auto; width: 350px; padding: 35px 35px 15px 35px; background: #fff; border: 1px solid #eaeaea; box-shadow: 0 0 25px #cac6c6; .title { margin: 0px auto 40px auto; text-align: center; color: #505458; .remember { margin: 0px 0px 35px 0px; /style 

token相关接口使用说明

方法功能说明特点TokenObtainPairView用户第一次登录,返回access和refresh的两个tokenaccess的token应该设置较短有效时间,refresh的token应该设置较长的合理有效时间TokenRefreshView传递有效时间内的refresh-token,接口返回有效时间的新access-tokenrefresh-token过期返回的状态码与access-token过期返回的状态码都是401(vue拦截器对此处理需要一点小技巧,请参考axios-filter.js)TokenVerifyView验证提交的token,返回当前token状态信息

settings.py中simplejwt相关设置参数

SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=1), 'REFRESH_TOKEN_LIFETIME': timedelta(minutes=2), 'ROTATE_REFRESH_TOKENS': False, 'BLACKLIST_AFTER_ROTATION': True, 'UPDATE_LAST_LOGIN': False, 'ALGORITHM': 'HS256', 'SIGNING_KEY': SECRET_KEY, 'VERIFYING_KEY': None, 'AUDIENCE': None, 'ISSUER': None, 'AUTH_HEADER_TYPES': ('JWt',), 'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION', 'USER_ID_FIELD': 'id', 'USER_ID_CLAIM': 'user_id', 'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule', 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',), 'TOKEN_TYPE_CLAIM': 'token_type', 'JTI_CLAIM': 'jti', 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5), 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),}

完整参数请参考:

实际应用中:verify_jwt_token调用的频率可能比较少,如果对安全性没太大要求,可以只使用access的token,不启用refresh的token,access的token超时后,跳转登录页即可。但当用户成功验证而应用程序不更新cookie时,这个时候就存在会话固定漏洞,攻击者可利用此漏洞发起会话劫持,所以建议设置——ACCESS_TOKEN_LIFETIME为较短时间,设置REFRESH_TOKEN_LIFETIME为合适的较长时间,即——access为较短的有效期,refresh设置为合理的较长有效期,前端不断携带refresh token刷新接口,获取新的access token来进行业务交互。

简述一下djangorestframework-jwt和djangorestframework-simplejwt的区别

关于djangorestframework-jwt的模块,在使用obtain_jwt_token方法时,只会返回一个token,且该token只能在固定有效期时间内调用refresh_jwt_token,获取新的token(新的token有效期等于前面所有token有效期减去已消耗的时间,也就是t1+t2+t3+..........=t1(如果没有刷新token)=JWT_EXPIRATION_DELTA;

Refresh with tokens can be repeated (token1 - token2 - token3), but this chain of token stores the time that the original token (obtained with username/password credentials), as orig_iat. You can only keep refreshing tokens up to JWT_REFRESH_EXPIRATION_DELTA.)

而如果使用djangorestframework-simplejwt模块,在使用TokenObtainPairView方法时,会直接返回两个(access和refresh)token,且设置不同有效期,携带refresh token访问TokenRefreshView,才能返回新的固定有效期的access token

参考链接:

标签: # 分享 # 技术
声明:生活头条网所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系admin@gdcyjd.com