改版登录接口

This commit is contained in:
liaoanqi
2022-03-31 16:03:39 +08:00
parent b918fad14f
commit 1c85f4c40d
19 changed files with 1416 additions and 106 deletions

View File

@@ -8,22 +8,22 @@
onShow: function() {
// 判断浏览器环境
var ua = navigator.userAgent.toLowerCase();
if (ua.search(/MicroMessenger/i) > -1 && !uni.getStorageSync('appType')) {
// 微信环境
uni.setStorageSync('appType', 2)
http.mpAuthLogin()
}
const state = util.getUrlKey('state')
const code = util.getUrlKey('code')
if ((state == 'needCode' || state == 'unNeedCode') && code) {
let path = window.location.href
if (path.indexOf('code=') > 0 && path.indexOf('&state=unNeedCode') > -1) {
http.mpLogin(null, code)
path = path.substring(0, path.indexOf('code=') - 1)
history.replaceState({}, '', path)
}
// if (ua.search(/MicroMessenger/i) > -1 && !uni.getStorageSync('appType')) {
// // 微信环境
// uni.setStorageSync('appType', 2)
// http.mpAuthLogin()
// }
// const state = util.getUrlKey('state')
// const code = util.getUrlKey('code')
// if ((state == 'needCode' || state == 'unNeedCode') && code) {
// let path = window.location.href
// if (path.indexOf('code=') > 0 && path.indexOf('&state=unNeedCode') > -1) {
// http.mpLogin(null, code)
// path = path.substring(0, path.indexOf('code=') - 1)
// history.replaceState({}, '', path)
// }
http.getCartCount()
}
// }
},
globalData: {
// 定义全局请求队列

View File

@@ -14,7 +14,10 @@
"author": "",
"license": "ISC",
"devDependencies": {
"uni-read-pages": "^1.0.5",
"query-string": "^6.13.1"
"query-string": "^6.13.1",
"uni-read-pages": "^1.0.5"
},
"dependencies": {
"crypto-js": "^4.1.1"
}
}

View File

@@ -33,6 +33,7 @@
<script>
var http = require("../../utils/http");
var util = require('../../utils/util.js');
import { encrypt } from '../../utils/crypto.js'
import {
AppType
} from '../../utils/constant.js'
@@ -156,24 +157,18 @@
})
// #ifdef H5 || APP-PLUS
var params = {
url: "/webLogin",
url: "/login",
method: "post",
data: {
"principal": this.principal,
"credentials": this.credentials
"userName": this.principal,
"passWord": encrypt(this.credentials)
},
callBack: res => {
console.log("login",res)
// var loginResult = '';
// uni.setStorageSync("loginResult",res);
// uni.setStorageSync('token', 'bearer' + res.access_token);
// return
http.loginSuccess(res, () => {
uni.showToast({
title: "登录成功",
icon: 'none',
complete: () => {
// this.$Router.pushTab('/pages/index/index')
setTimeout(() => {
wx.switchTab({
url: '/pages/index/index'
@@ -188,25 +183,25 @@
http.request(params)
// #endif
// #ifdef MP-WEIXIN
wx.login({
success: (res) => {
var params = {
url: "/login",
method: "post",
data: {
appType: 1,
credentials: this.credentials,
loginType: 0,
principal: this.principal + ':' + res.code
},
callBack: result => {
http.loginSuccess(result)
this.$Router.pushTab('/pages/index/index')
},
}
http.request(params)
},
})
// wx.login({
// success: (res) => {
// var params = {
// url: "/login",
// method: "post",
// data: {
// appType: 1,
// credentials: this.credentials,
// loginType: 0,
// principal: this.principal + ':' + res.code
// },
// callBack: result => {
// http.loginSuccess(result)
// this.$Router.pushTab('/pages/index/index')
// },
// }
// http.request(params)
// },
// })
// #endif
}
},

View File

@@ -39,6 +39,7 @@
// pages/register/register.js
var http = require("../../utils/http");
var util = require("../../utils/util.js");
import { encrypt } from '../../utils/crypto.js'
export default {
data() {
@@ -143,11 +144,10 @@
data: {
// appType: 1,
// 应用类型 1小程序 2微信公众号 3 PC 4 H5
userMail: this.principal,
password: this.credentials,
userName: this.principal,
passWord: encrypt(this.credentials),
},
callBack: res => {
console.log("1111",res)
uni.hideLoading();
uni.showToast({
title: "注册成功,请登录",

View File

@@ -323,8 +323,8 @@
logout: function() {
// 请求退出登陆接口
http.request({
url: '/p/user/logout',
method: 'GET',
url: '/logOut',
method: 'post',
callBack: res => {
util.removeTabBadge()
@@ -336,7 +336,7 @@
title: "退出成功",
icon: "none"
})
this.setData({
orderAmount: ''
});

11
mall4uni/utils/crypto.js Normal file
View File

@@ -0,0 +1,11 @@
import CryptoJS from 'crypto-js'
// 加密
const keyStr = '-mall4j-password' // 解密用的key
export function encrypt (word) {
const time = Date.now()
const key = CryptoJS.enc.Utf8.parse(keyStr)
const srcs = CryptoJS.enc.Utf8.parse(time + word) // 加密方式: 时间戳 + 密文
const encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7})
return encrypted.toString()
}

View File

@@ -19,9 +19,9 @@ function request(params, isGetTonken) {
params.data = params.data + '';
}
var needToken = false
if (params.url.indexOf("/p/") == 0 || params.url.indexOf("/user/registerOrBindUser") == 0) {
needToken = true
}
// if (params.url.indexOf("/p/") == 0 || params.url.indexOf("/user/registerOrBindUser") == 0) {
// needToken = true
// }
wx.request({
// url: config.domain + params.url,
@@ -31,7 +31,7 @@ function request(params, isGetTonken) {
header: {
// 'content-type': params.method == "GET" ? 'application/x-www-form-urlencoded' : 'application/json;charset=utf-8',
// 'Authorization': params.login ? undefined : uni.getStorageSync('token')
'Authorization': !needToken ? undefined : uni.getStorageSync('token') || uni.getStorageSync('tempToken'),
'Authorization': uni.getStorageSync('token') ,
},
method: params.method == undefined ? "POST" : params.method,
dataType: 'json',
@@ -247,24 +247,24 @@ var getToken = function (fn) {
* @param {Object} fn 登录成功后的回调
*/
function loginSuccess (result, fn) {
if (!result.enabled) {
uni.showModal({
showCancel: false,
title: "提示",
content: "您已被禁用,不能购买,请联系客服",
cancelText: "取消",
confirmText: "确定",
success: function (res) {
if (res.confirm) {
wx.switchTab({
url: '/pages/index/index'
});
}
}
})
wx.setStorageSync('token', '');
return
}
// if (!result.enabled) {
// uni.showModal({
// showCancel: false,
// title: "提示",
// content: "您已被禁用,不能购买,请联系客服",
// cancelText: "取消",
// confirmText: "确定",
// success: function (res) {
// if (res.confirm) {
// wx.switchTab({
// url: '/pages/index/index'
// });
// }
// }
// })
// wx.setStorageSync('token', '');
// return
// }
// 保存登陆信息
wx.setStorageSync('loginResult', result)
@@ -273,21 +273,53 @@ function loginSuccess (result, fn) {
// 没有获取到用户昵称,说明服务器没有保存用户的昵称,也就是用户授权的信息并没有传到服务器
// if (!result.pic) {
// updateUserInfo();
// }
// }
const expiresTimeStamp = result.expiresIn * 1000 / 2 + new Date().getTime()
// 缓存token的过期时间
uni.setStorageSync('expiresTimeStamp', expiresTimeStamp)
wx.setStorageSync('token', 'bearer' + result.access_token); //把token存入缓存请求接口数据时要用
wx.setStorageSync('token', result.accessToken); //把token存入缓存请求接口数据时要用
if (result.userId) {
wx.setStorageSync('hadBindUser', true);
getCartCount()
} else {
wx.setStorageSync('hadBindUser', false);
}
// var globalData = getApp().globalData;
// globalData.isLanding = false;
// while (globalData.requestQueue.length) {
// request(globalData.requestQueue.pop());
// }
// const routeUrlAfterLogin = uni.getStorageSync('routeUrlAfterLogin')
// const pages = getCurrentPages()
// if (pages.length === 1) {
// uni.reLaunch({
// url: routeUrlAfterLogin
// })
// uni.removeStorageSync('routeUrlAfterLogin')
// return
// }
// const prevPage = pages[pages.length - 2]
// if (!prevPage) {
// wx.switchTab({
// url: '/pages/index/index'
// });
// return
// }
// // 判断上一页面是否为tabbar页面 (首页和分类页无需登录接口)
// const isTabbar = prevPage.route === 'pages/user/user' || prevPage.route === 'pages/basket/basket'
// if (isTabbar) {
// wx.switchTab({
// url: '/' + prevPage.route
// });
// } else {
// // 非tabbar页面
// let backDelata = 0
// pages.forEach((page, index) => {
// if (page.$page.fullPath === routeUrlAfterLogin) {
// backDelata = pages.length - index - 1
// }
// })
// if (backDelata) {
// uni.navigateBack({
// delta: backDelata
// })
// } else {
// wx.switchTab({
// url: '/pages/index/index'
// });
// }
// }
if (fn) {
fn()

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,268 @@
<template>
<div
style="position: relative"
>
<div class="verify-img-out">
<div
class="verify-img-panel"
:style="{'width': setSize.imgWidth,
'height': setSize.imgHeight,
'background-size' : setSize.imgWidth + ' '+ setSize.imgHeight,
'margin-bottom': vSpace + 'px'}"
>
<div v-show="showRefresh" class="verify-refresh" style="z-index:3" @click="refresh">
<i class="iconfont icon-refresh" />
</div>
<img
ref="canvas"
:src="pointBackImgBase?('data:image/png;base64,'+pointBackImgBase):defaultImg"
alt=""
style="width:100%;height:100%;display:block"
@click="bindingClick?canvasClick($event):undefined"
>
<div
v-for="(tempPoint, index) in tempPoints"
:key="index"
class="point-area"
:style="{
'background-color':'#1abd6c',
color:'#fff',
'z-index':9999,
width:'20px',
height:'20px',
'text-align':'center',
'line-height':'20px',
'border-radius': '50%',
position:'absolute',
top:parseInt(tempPoint.y-10) + 'px',
left:parseInt(tempPoint.x-10) + 'px'
}"
>
{{ index + 1 }}
</div>
</div>
</div>
<!-- 'height': this.barSize.height, -->
<div
class="verify-bar-area"
:style="{'width': setSize.imgWidth,
'color': this.barAreaColor,
'border-color': this.barAreaBorderColor,
'line-height':this.barSize.height}"
>
<span class="verify-msg">{{ text }}</span>
</div>
</div>
</template>
<script type="text/babel">
/**
* VerifyPoints
* @description 点选
* */
import { resetSize, _code_chars, _code_color1, _code_color2 } from './../utils/util'
import { aesEncrypt } from './../utils/ase'
import { reqGet, reqCheck } from './../api/index'
export default {
name: 'VerifyPoints',
props: {
// 弹出式pop固定fixed
mode: {
type: String,
default: 'fixed'
},
captchaType: {
type: String,
},
// 间隔
vSpace: {
type: Number,
default: 5
},
imgSize: {
type: Object,
default() {
return {
width: '310px',
height: '155px'
}
}
},
barSize: {
type: Object,
default() {
return {
width: '310px',
height: '40px'
}
}
},
defaultImg: {
type: String,
default: ''
}
},
data() {
return {
secretKey: '', // 后端返回的ase加密秘钥
checkNum: 3, // 默认需要点击的字数
fontPos: [], // 选中的坐标信息
checkPosArr: [], // 用户点击的坐标
num: 1, // 点击的记数
pointBackImgBase: '', // 后端获取到的背景图片
poinTextList: [], // 后端返回的点击字体顺序
backToken: '', // 后端返回的token值
setSize: {
imgHeight: 0,
imgWidth: 0,
barHeight: 0,
barWidth: 0
},
tempPoints: [],
text: '',
barAreaColor: undefined,
barAreaBorderColor: undefined,
showRefresh: true,
bindingClick: true
}
},
computed: {
resetSize() {
return resetSize
}
},
watch: {
// type变化则全面刷新
type: {
immediate: true,
handler() {
this.init()
}
}
},
mounted() {
// 禁止拖拽
this.$el.onselectstart = function() {
return false
}
},
methods: {
init() {
// 加载页面
this.fontPos.splice(0, this.fontPos.length)
this.checkPosArr.splice(0, this.checkPosArr.length)
this.num = 1
this.getPictrue()
this.$nextTick(() => {
this.setSize = this.resetSize(this) // 重新设置宽度高度
this.$parent.$emit('ready', this)
})
},
canvasClick(e) {
this.checkPosArr.push(this.getMousePos(this.$refs.canvas, e))
if (this.num == this.checkNum) {
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e))
// 按比例转换坐标值
this.checkPosArr = this.pointTransfrom(this.checkPosArr, this.setSize)
// 等创建坐标执行完
setTimeout(() => {
// var flag = this.comparePos(this.fontPos, this.checkPosArr);
// 发送后端请求
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify(this.checkPosArr), this.secretKey) : this.backToken + '---' + JSON.stringify(this.checkPosArr)
const data = {
captchaType: this.captchaType,
'pointJson': this.secretKey ? aesEncrypt(JSON.stringify(this.checkPosArr), this.secretKey) : JSON.stringify(this.checkPosArr),
'token': this.backToken
}
reqCheck(data).then(res => {
if (res.repCode == '0000') {
this.barAreaColor = '#4cae4c'
this.barAreaBorderColor = '#5cb85c'
this.text = '验证成功'
this.bindingClick = false
if (this.mode == 'pop') {
setTimeout(() => {
this.$parent.clickShow = false
this.refresh()
}, 1500)
}
this.$parent.$emit('success', { captchaVerification })
} else {
this.$parent.$emit('error', this)
this.barAreaColor = '#d9534f'
this.barAreaBorderColor = '#d9534f'
this.text = '验证失败'
setTimeout(() => {
this.refresh()
}, 700)
}
})
}, 400)
}
if (this.num < this.checkNum) {
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e))
}
},
// 获取坐标
getMousePos: function(obj, e) {
var x = e.offsetX
var y = e.offsetY
return { x, y }
},
// 创建坐标点
createPoint: function(pos) {
this.tempPoints.push(Object.assign({}, pos))
return ++this.num
},
refresh: function() {
this.tempPoints.splice(0, this.tempPoints.length)
this.barAreaColor = '#000'
this.barAreaBorderColor = '#ddd'
this.bindingClick = true
this.fontPos.splice(0, this.fontPos.length)
this.checkPosArr.splice(0, this.checkPosArr.length)
this.num = 1
this.getPictrue()
this.text = '验证失败'
this.showRefresh = true
},
// 请求背景图片和验证图片
getPictrue() {
const data = {
captchaType: this.captchaType,
clientUid: localStorage.getItem('point'),
ts: Date.now(), // 现在的时间戳
}
reqGet(data).then(res => {
if (res.repCode == '0000') {
this.pointBackImgBase = res.repData.originalImageBase64
this.backToken = res.repData.token
this.secretKey = res.repData.secretKey
this.poinTextList = res.repData.wordList
this.text = '请依次点击【' + this.poinTextList.join(',') + '】'
} else {
this.text = res.repMsg
}
// 判断接口请求次数是否失效
if (res.repCode == '6201') {
this.pointBackImgBase = null
}
})
},
// 坐标转换函数
pointTransfrom(pointArr, imgSize) {
var newPointArr = pointArr.map(p => {
const x = Math.round(310 * p.x / parseInt(imgSize.imgWidth))
const y = Math.round(155 * p.y / parseInt(imgSize.imgHeight))
return { x, y }
})
// console.log(newPointArr,"newPointArr");
return newPointArr
}
},
}
</script>

View File

@@ -0,0 +1,378 @@
<template>
<div style="position: relative;">
<div
v-if="type === '2'"
class="verify-img-out"
:style="{height: (parseInt(setSize.imgHeight) + vSpace) + 'px'}"
>
<div
class="verify-img-panel"
:style="{width: setSize.imgWidth,
height: setSize.imgHeight,}"
>
<img :src="backImgBase?('data:image/png;base64,'+backImgBase):defaultImg" alt="" style="width:100%;height:100%;display:block">
<div v-show="showRefresh" class="verify-refresh" @click="refresh"><i class="iconfont icon-refresh" />
</div>
<transition name="tips">
<span v-if="tipWords" class="verify-tips" :class="passFlag ?'suc-bg':'err-bg'">{{ tipWords }}</span>
</transition>
</div>
</div>
<!-- 公共部分 -->
<div
class="verify-bar-area"
:style="{width: setSize.imgWidth,
height: barSize.height,
'line-height':barSize.height}"
>
<span class="verify-msg" v-text="text" />
<div
class="verify-left-bar"
:style="{width: (leftBarWidth!==undefined)?leftBarWidth: barSize.height, height: barSize.height, 'border-color': leftBarBorderColor, transaction: transitionWidth}"
>
<span class="verify-msg" v-text="finishText" />
<div
class="verify-move-block"
:style="{width: barSize.height, height: barSize.height, 'background-color': moveBlockBackgroundColor, left: moveBlockLeft, transition: transitionLeft}"
@touchstart="start"
@mousedown="start"
>
<i
:class="['verify-icon iconfont', iconClass]"
:style="{color: iconColor}"
/>
<div
v-if="type === '2'"
class="verify-sub-block"
:style="{'width':Math.floor(parseInt(setSize.imgWidth)*47/310)+ 'px',
'height': setSize.imgHeight,
'top':'-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
}"
>
<img :src="'data:image/png;base64,'+blockBackImgBase" alt="" style="width:100%;height:100%;display:block">
</div>
</div>
</div>
</div>
</div>
</template>
<script type="text/babel">
/**
* VerifySlide
* @description 滑块
* */
import { aesEncrypt } from './../utils/ase'
import { resetSize } from './../utils/util'
import { reqGet, reqCheck } from './../api/index'
// "captchaType":"blockPuzzle",
export default {
name: 'VerifySlide',
props: {
captchaType: {
type: String,
},
type: {
type: String,
default: '1'
},
// 弹出式pop固定fixed
mode: {
type: String,
default: 'fixed'
},
vSpace: {
type: Number,
default: 5
},
explain: {
type: String,
default: '向右滑动完成验证'
},
imgSize: {
type: Object,
default() {
return {
width: '310px',
height: '155px'
}
}
},
blockSize: {
type: Object,
default() {
return {
width: '50px',
height: '50px'
}
}
},
barSize: {
type: Object,
default() {
return {
width: '310px',
height: '40px'
}
}
},
defaultImg: {
type: String,
default: ''
}
},
data() {
return {
secretKey: '', // 后端返回的加密秘钥 字段
passFlag: '', // 是否通过的标识
backImgBase: '', // 验证码背景图片
blockBackImgBase: '', // 验证滑块的背景图片
backToken: '', // 后端返回的唯一token值
startMoveTime: '', // 移动开始的时间
endMovetime: '', // 移动结束的时间
tipsBackColor: '', // 提示词的背景颜色
tipWords: '',
text: '',
finishText: '',
setSize: {
imgHeight: 0,
imgWidth: 0,
barHeight: 0,
barWidth: 0
},
top: 0,
left: 0,
moveBlockLeft: undefined,
leftBarWidth: undefined,
// 移动中样式
moveBlockBackgroundColor: undefined,
leftBarBorderColor: '#ddd',
iconColor: undefined,
iconClass: 'icon-right',
status: false, // 鼠标状态
isEnd: false, // 是够验证完成
showRefresh: true,
transitionLeft: '',
transitionWidth: ''
}
},
computed: {
barArea() {
return this.$el.querySelector('.verify-bar-area')
},
resetSize() {
return resetSize
}
},
watch: {
// type变化则全面刷新
type: {
immediate: true,
handler() {
this.init()
}
}
},
mounted() {
// 禁止拖拽
this.$el.onselectstart = function() {
return false
}
console.log(this.defaultImg)
},
methods: {
init() {
this.text = this.explain
this.getPictrue()
this.$nextTick(() => {
const setSize = this.resetSize(this) // 重新设置宽度高度
for (const key in setSize) {
this.$set(this.setSize, key, setSize[key])
}
this.$parent.$emit('ready', this)
})
var _this = this
window.removeEventListener('touchmove', function(e) {
_this.move(e)
})
window.removeEventListener('mousemove', function(e) {
_this.move(e)
})
// 鼠标松开
window.removeEventListener('touchend', function() {
_this.end()
})
window.removeEventListener('mouseup', function() {
_this.end()
})
window.addEventListener('touchmove', function(e) {
_this.move(e)
})
window.addEventListener('mousemove', function(e) {
_this.move(e)
})
// 鼠标松开
window.addEventListener('touchend', function() {
_this.end()
})
window.addEventListener('mouseup', function() {
_this.end()
})
},
// 鼠标按下
start: function(e) {
e = e || window.event
if (!e.touches) { // 兼容PC端
var x = e.clientX
} else { // 兼容移动端
var x = e.touches[0].pageX
}
this.startLeft = Math.floor(x - this.barArea.getBoundingClientRect().left)
this.startMoveTime = +new Date() // 开始滑动的时间
if (this.isEnd == false) {
this.text = ''
this.moveBlockBackgroundColor = '#337ab7'
this.leftBarBorderColor = '#337AB7'
this.iconColor = '#fff'
e.stopPropagation()
this.status = true
}
},
// 鼠标移动
move: function(e) {
e = e || window.event
if (this.status && this.isEnd == false) {
if (!e.touches) { // 兼容PC端
var x = e.clientX
} else { // 兼容移动端
var x = e.touches[0].pageX
}
var bar_area_left = this.barArea.getBoundingClientRect().left
var move_block_left = x - bar_area_left // 小方块相对于父元素的left值
if (move_block_left >= this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2) {
move_block_left = this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2
}
if (move_block_left <= 0) {
move_block_left = parseInt(parseInt(this.blockSize.width) / 2)
}
// 拖动后小方块的left值
this.moveBlockLeft = (move_block_left - this.startLeft) + 'px'
this.leftBarWidth = (move_block_left - this.startLeft) + 'px'
}
},
// 鼠标松开
end: function() {
this.endMovetime = +new Date()
var _this = this
// 判断是否重合
if (this.status && this.isEnd == false) {
var moveLeftDistance = parseInt((this.moveBlockLeft || '').replace('px', ''))
moveLeftDistance = moveLeftDistance * 310 / parseInt(this.setSize.imgWidth)
const data = {
captchaType: this.captchaType,
'pointJson': this.secretKey ? aesEncrypt(JSON.stringify({ x: moveLeftDistance, y: 5.0 }), this.secretKey) : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
'token': this.backToken
}
reqCheck(data).then(res => {
res = res.data
if (res.repCode == '0000') {
this.moveBlockBackgroundColor = '#5cb85c'
this.leftBarBorderColor = '#5cb85c'
this.iconColor = '#fff'
this.iconClass = 'icon-check'
this.showRefresh = false
this.isEnd = true
if (this.mode == 'pop') {
setTimeout(() => {
this.$parent.clickShow = false
this.refresh()
}, 1500)
}
this.passFlag = true
this.tipWords = `${((this.endMovetime - this.startMoveTime) / 1000).toFixed(2)}s验证成功`
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 }), this.secretKey) : this.backToken + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 })
setTimeout(() => {
this.tipWords = ''
this.$parent.closeBox()
this.$parent.$emit('success', { captchaVerification })
}, 1000)
} else {
this.moveBlockBackgroundColor = '#d9534f'
this.leftBarBorderColor = '#d9534f'
this.iconColor = '#fff'
this.iconClass = 'icon-close'
this.passFlag = false
setTimeout(function() {
_this.refresh()
}, 1000)
this.$parent.$emit('error', this)
this.tipWords = '验证失败'
setTimeout(() => {
this.tipWords = ''
}, 1000)
}
})
this.status = false
}
},
refresh: function() {
this.showRefresh = true
this.finishText = ''
this.transitionLeft = 'left .3s'
this.moveBlockLeft = 0
this.leftBarWidth = undefined
this.transitionWidth = 'width .3s'
this.leftBarBorderColor = '#ddd'
this.moveBlockBackgroundColor = '#fff'
this.iconColor = '#000'
this.iconClass = 'icon-right'
this.isEnd = false
this.getPictrue()
setTimeout(() => {
this.transitionWidth = ''
this.transitionLeft = ''
this.text = this.explain
}, 300)
},
// 请求背景图片和验证图片
getPictrue() {
const data = {
captchaType: this.captchaType,
clientUid: localStorage.getItem('slider'),
ts: Date.now(), // 现在的时间戳
}
reqGet(data).then(res => {
if (res.data.repCode == '0000') {
this.backImgBase = res.data.repData.originalImageBase64
this.blockBackImgBase = res.data.repData.jigsawImageBase64
this.backToken = res.data.repData.token
this.secretKey = res.data.repData.secretKey
} else {
this.tipWords = res.data.repMsg
}
// 判断接口请求次数是否失效
if (res.data.repCode == '6201') {
this.backImgBase = null
this.blockBackImgBase = null
}
})
},
},
}
</script>

View File

@@ -0,0 +1,24 @@
/**
* 此处可直接引用自己项目封装好的 axios 配合后端联调
*/
import httpRequest from '@/utils/httpRequest'
// 获取验证图片 以及token
export function reqGet (data) {
return httpRequest({
url: httpRequest.adornUrl('/captcha/get'),
method: 'post',
data
})
}
// 滑动或者点选验证
export function reqCheck (data) {
return httpRequest({
url: httpRequest.adornUrl('/captcha/check'),
method: 'post',
data
})
}

View File

@@ -0,0 +1,11 @@
import CryptoJS from 'crypto-js'
/**
* @word 要加密的内容
* @keyWord String 服务器随机返回的关键字
* */
export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') {
var key = CryptoJS.enc.Utf8.parse(keyWord)
var srcs = CryptoJS.enc.Utf8.parse(word)
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
return encrypted.toString()
}

View File

@@ -0,0 +1,36 @@
export function resetSize(vm) {
var img_width, img_height, bar_width, bar_height // 图片的宽度、高度,移动条的宽度、高度
var parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
var parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
if (vm.imgSize.width.indexOf('%') != -1) {
img_width = parseInt(this.imgSize.width) / 100 * parentWidth + 'px'
} else {
img_width = this.imgSize.width
}
if (vm.imgSize.height.indexOf('%') != -1) {
img_height = parseInt(this.imgSize.height) / 100 * parentHeight + 'px'
} else {
img_height = this.imgSize.height
}
if (vm.barSize.width.indexOf('%') != -1) {
bar_width = parseInt(this.barSize.width) / 100 * parentWidth + 'px'
} else {
bar_width = this.barSize.width
}
if (vm.barSize.height.indexOf('%') != -1) {
bar_height = parseInt(this.barSize.height) / 100 * parentHeight + 'px'
} else {
bar_height = this.barSize.height
}
return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height }
}
export const _code_chars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']

View File

@@ -0,0 +1,11 @@
import CryptoJS from 'crypto-js'
// 加密
const keyStr = '-mall4j-password' // 解密用的key
export function encrypt(word){
const time = Date.now();
const key = CryptoJS.enc.Utf8.parse(keyStr);
const srcs = CryptoJS.enc.Utf8.parse(time + word); // 加密方式: 时间戳 + 密文
const encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}

View File

@@ -20,7 +20,7 @@ export function isAuth (key) {
if (authorities.length) {
for (const i in authorities) {
const element = authorities[i]
if (element.authority === key) {
if (element === key) {
return true
}
}

View File

@@ -22,7 +22,7 @@
type="password"
placeholder="密码"></el-input>
</el-form-item>
<el-form-item prop="captcha">
<!-- <el-form-item prop="captcha">
<el-row :gutter="20">
<el-col :span="14">
<el-input v-model="dataForm.captcha"
@@ -36,7 +36,7 @@
alt="">
</el-col>
</el-row>
</el-form-item>
</el-form-item> -->
<el-form-item>
<div class="item-btn"><input type="button"
value="登录"
@@ -47,12 +47,23 @@
<div class="bottom">Copyright © 2019 广州市蓝海创新科技有限公司</div>
</div>
<Verify
ref="verify"
:captcha-type="'blockPuzzle'"
:img-size="{width:'400px',height:'200px'}"
@success="login"
/>
</div>
</template>
<script>
import { getUUID } from '@/utils'
import Verify from '@/components/verifition/Verify'
import { encrypt } from '@/utils/crypto'
export default {
components: {
Verify
},
data () {
return {
dataForm: {
@@ -75,32 +86,70 @@ export default {
captchaPath: ''
}
},
beforeDestroy () {
document.removeEventListener('keyup', this.handerKeyup)
},
created () {
this.getCaptcha()
document.addEventListener('keyup', this.handerKeyup)
},
methods: {
handerKeyup (e) {
var keycode = document.all ? event.keyCode : e.which
if (keycode === 13) {
this.dataFormSubmit()
}
},
// 提交表单
dataFormSubmit () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.$http({
url: this.$http.adornUrl('/login?grant_type=admin'),
method: 'post',
data: this.$http.adornData({
'principal': this.dataForm.userName,
'credentials': this.dataForm.password,
'sessionUUID': this.dataForm.uuid,
'imageCode': this.dataForm.captcha
})
}).then(({ data }) => {
this.$cookie.set('Authorization', 'bearer' + data.access_token)
this.$router.replace({ name: 'home' })
}).catch(() => {
this.getCaptcha()
})
this.$refs.verify.show()
}
})
},
login (verifyResult) {
if (this.isSubmit) {
return
}
this.isSubmit = true
this.$http({
url: this.$http.adornUrl('/adminLogin'),
method: 'post',
data: this.$http.adornData({
'userName': this.dataForm.userName,
'passWord': encrypt(this.dataForm.password),
'captchaVerification': verifyResult.captchaVerification
})
}).then(({ data }) => {
this.$cookie.set('Authorization', data.accessToken)
this.$router.replace({ name: 'home' })
}).catch(() => {
this.isSubmit = false
})
},
// dataFormSubmit () {
// this.$refs['dataForm'].validate((valid) => {
// if (valid) {
// this.$http({
// url: this.$http.adornUrl('/login?grant_type=admin'),
// method: 'post',
// data: this.$http.adornData({
// 'principal': this.dataForm.userName,
// 'credentials': this.dataForm.password,
// 'sessionUUID': this.dataForm.uuid,
// 'imageCode': this.dataForm.captcha
// })
// }).then(({ data }) => {
// this.$cookie.set('Authorization', 'bearer' + data.access_token)
// this.$router.replace({ name: 'home' })
// }).catch(() => {
// this.getCaptcha()
// })
// }
// })
// },
// 获取验证码
getCaptcha () {
this.dataForm.uuid = getUUID()

View File

@@ -79,7 +79,7 @@
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl('/sys/logout'),
url: this.$http.adornUrl('/logOut'),
method: 'post',
data: this.$http.adornData()
}).then(({data}) => {

View File

@@ -41,6 +41,7 @@
<script>
import { isEmail, isMobile } from '@/utils/validate'
import { Debounce } from '@/utils/debounce'
import { encrypt } from '@/utils/crypto'
export default {
data () {
var validatePassword = (rule, value, callback) => {
@@ -149,7 +150,7 @@
data: this.$http.adornData({
'userId': this.dataForm.id || undefined,
'username': this.dataForm.userName,
'password': this.dataForm.password,
'password': encrypt(this.dataForm.password),
'email': this.dataForm.email,
'mobile': this.dataForm.mobile,
'status': this.dataForm.status,