Skip to content

Commit

Permalink
feat: rsa 前端加密 #808
Browse files Browse the repository at this point in the history
  • Loading branch information
yuri0528 authored and EmilyMei committed Dec 16, 2022
1 parent 92a6894 commit 3f22a86
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 26 deletions.
1 change: 1 addition & 0 deletions src/pages/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"express-art-template": "1.0.1",
"intl-tel-input": "16.0.0",
"js-base64": "^3.7.2",
"jsencrypt": "^3.3.1",
"jsonp": "0.2.1",
"query-string": "6.5.0",
"sortablejs": "1.10.1",
Expand Down
30 changes: 30 additions & 0 deletions src/pages/src/common/rsa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* by making 蓝鲸智云-用户管理(Bk-User) available.
* Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
/* 数据RSA加密 */
import JSEncrypt from 'jsencrypt';

export default {
// JSEncrypt 加密
rsaPublicData(data, publicKey) {
const jsencrypt = new JSEncrypt();
jsencrypt.setPublicKey(publicKey);
const result = jsencrypt.encrypt(data);
return result;
},
// JSEncrypt 解密
rsaPrivateData(data, privateKey) {
const jsencrypt = new JSEncrypt();
jsencrypt.setPrivateKey(privateKey);
const result = jsencrypt.encrypt(data);
return result;
},
};
2 changes: 2 additions & 0 deletions src/pages/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import bus from '@/common/bus';
import cursor from '@/directives/cursor';
import { Base64 } from 'js-base64';
import xss from 'xss';
import Rsa from '@/common/rsa';

Vue.component(VueCropper);
Vue.use(vClickOutside);
Expand All @@ -35,6 +36,7 @@ Vue.directive('cursor', cursor);
Vue.config.devtools = true;
Vue.prototype.$bus = new Vue();
Vue.use(Base64);
Vue.prototype.Rsa = Rsa;
Vue.prototype.$xss = (html) => {
const attrs = ['class', 'title', 'target', 'style', 'src', 'onerror'];
return xss(html || '', {
Expand Down
4 changes: 4 additions & 0 deletions src/pages/src/store/modules/password.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ export default {
sendCode(context, params, config = {}) {
return http.post('api/v1/web/passwords/reset/verification_code/verify/', params);
},
// 获取rsa公钥
getRsa(context, params, config = {}) {
return http.get(`api/v1/web/passwords/settings/by_token/?token=${params}`);
},
},
};
37 changes: 32 additions & 5 deletions src/pages/src/views/organization/details/UserMaterial.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@

<script>
import { dateConvert } from '@/common/util';
const Base64 = require('js-base64').Base64;
export default {
directives: {
focus: {
Expand Down Expand Up @@ -200,6 +201,10 @@ export default {
newPassword: 'password',
},
passwordRules: null,
// 公钥
publicKey: '',
// 是否rsa加密
isRsaEncrypted: false,
};
},
computed: {
Expand Down Expand Up @@ -304,14 +309,27 @@ export default {
this.phoneNumber = this.currentProfile.telephone;
},
// 重置密码
showResetDialog() {
async showResetDialog() {
if (this.isForbid) {
return;
}
this.isShowReset = true;
// 清空上次输入
this.oldPassword = '';
this.newPassword = '';
const res = await this.$store.dispatch('catalog/ajaxGetPassport', {
id: this.currentCategoryId,
});
if (res.data) {
res.data.forEach((item) => {
if (item.key === 'enable_password_rsa_encrypted') {
this.isRsaEncrypted = true;
}
if (item.key === 'password_rsa_public_key') {
this.publicKey = Base64.decode(item.value);
}
});
}
},
// 验证密码的格式
async confirmReset() {
Expand Down Expand Up @@ -381,10 +399,19 @@ export default {
if (this.isAdmin) {
passwordData.old_password = this.oldPassword.trim();
};
await this.$store.dispatch('organization/patchProfile', {
id: this.currentProfile.id,
data: passwordData,
});
if (this.isRsaEncrypted) {
await this.$store.dispatch('organization/patchProfile', {
id: this.currentProfile.id,
data: {
password: this.Rsa.rsaPublicData(passwordData, this.publicKey),
},
});
} else {
await this.$store.dispatch('organization/patchProfile', {
id: this.currentProfile.id,
data: passwordData,
});
}
this.$bkMessage({
message: this.$t('重置密码成功'),
theme: 'success',
Expand Down
70 changes: 62 additions & 8 deletions src/pages/src/views/password/Modify.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</div>
<div class="modify-content" data-test-id="passwordInfo">
<h4 class="common-title">{{$t('更改密码')}}</h4>
<p class="error-text" v-if="isConfirmError">
<p class="error-text" v-if="isConfirmError || isCorrectPw">
<i class="icon icon-user-exclamation-circle-shape"></i>
<span class="text">{{errorText}}</span>
</p>
Expand All @@ -42,18 +42,18 @@
<li class="input-list">
<input
type="password"
:class="['select-text', { 'input-error': isConfirmError }]"
:class="['select-text', { 'input-error': isConfirmError || isCorrectPw }]"
:placeholder="$t('新密码')"
v-model="newPassword"
@focus="isConfirmError = false" />
@focus="handleFocus" />
</li>
<li class="input-list">
<input
type="password"
:class="['select-text', { 'input-error': isConfirmError }]"
:class="['select-text', { 'input-error': isConfirmError || isCorrectPw }]"
:placeholder="$t('确认新密码')"
v-model="confirmPassword"
@focus="isConfirmError = false" />
@focus="handleFocus" />
</li>
</ul>
<bk-button
Expand Down Expand Up @@ -85,26 +85,76 @@ export default {
data() {
return {
isConfirmError: false,
errorText: this.$t('两次输入的密码不一致,请重新输入'),
errorText: '',
oldPassword: '',
newPassword: '',
confirmPassword: '',
successDialog: {
isShow: false,
title: this.$t('密码修改成功'),
},
// 公钥
publicKey: '',
// 是否rsa加密
isRsaEncrypted: false,
passwordRules: {
passwordMinLength: 0,
passwordMustIncludes: [],
},
isCorrectPw: false,
};
},
mounted() {
this.initRsa();
},
methods: {
async initRsa() {
try {
const res = await this.$store.dispatch('password/getRsa', this.$route.query.token);
if (res.data) {
res.data.forEach((item) => {
switch (item.key) {
case 'enable_password_rsa_encrypted':
return this.isRsaEncrypted = true;
case 'password_rsa_public_key':
return this.publicKey = Base64.decode(item.value);
case 'password_min_length':
return this.passwordRules.passwordMinLength = item.value;
case 'password_must_includes':
return this.passwordRules.passwordMustIncludes = item.value;
}
});
}
} catch (e) {
console.warn(e);
}
},
async handlePush() {
try {
// 确认密码是否一致
if (this.newPassword !== this.confirmPassword) {
this.isConfirmError = true;
this.errorText = this.$t('两次输入的密码不一致,请重新输入');
return;
}
// 校验密码规则
this.isCorrectPw = !this.$validatePassportByRules(this.newPassword, this.passwordRules);
if (this.isCorrectPw) {
this.errorText = this.$getMessageByRules(this, this.passwordRules);
return;
}
if (this.isRsaEncrypted) {
this.oldPassword = Base64.encode(this.Rsa.rsaPublicData(this.oldPassword.trim(), this.publicKey));
this.newPassword = Base64.encode(this.Rsa.rsaPublicData(this.newPassword.trim(), this.publicKey));
this.confirmPassword = Base64.encode(this.Rsa.rsaPublicData(this.confirmPassword.trim(), this.publicKey));
} else {
this.oldPassword = Base64.encode(this.oldPassword.trim());
this.newPassword = Base64.encode(this.newPassword.trim());
this.confirmPassword = Base64.encode(this.confirmPassword.trim());
}
const modifyParams = {
old_password: Base64.encode(this.oldPassword),
new_password: Base64.encode(this.confirmPassword.trim()),
old_password: this.oldPassword,
new_password: this.confirmPassword,
};
await this.$store.dispatch('password/modify', modifyParams);
this.successDialog.isShow = true;
Expand All @@ -115,6 +165,10 @@ export default {
register() {
window.location.href = window.login_url;
},
handleFocus() {
this.isError = false;
this.isCorrectPw = false;
},
},
};
</script>
Expand Down
76 changes: 63 additions & 13 deletions src/pages/src/views/password/Set.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,26 @@
<h4 class="common-title">{{$t('设置新密码')}}</h4>
<p
v-if="setPasswordText"
:class="['text', isError && 'show-error-info']">
{{setPasswordText}}{{$t('_需要设置新密码')}}
</p>
<p class="error-text" v-if="isError">
:class="['text', isError && 'show-error-info']">{{setPasswordText}}{{$t('_需要设置新密码')}}</p>
<p
v-else
:class="['text', isError && 'show-error-info']">{{$t('请输入新密码进行密码重设')}}</p>
<p class="error-text" v-if="isError || isCorrectPw">
<i class="icon icon-user-exclamation-circle-shape"></i>
<span class="text">{{errorText}}</span>
</p>
<input
type="password"
:class="['select-text', { 'input-error': isError }]"
:class="['select-text', { 'input-error': isError || isCorrectPw }]"
:placeholder="$t('请输入新密码')"
v-model="password"
@focus="isError = false" />
@focus="handleFocus" />
<input
type="password"
:class="['select-text', { 'input-error': isError }]"
:class="['select-text', { 'input-error': isError || isCorrectPw }]"
:placeholder="$t('请再次确认新密码')"
v-model="confirmPassword"
@focus="isError = false" />
@focus="handleFocus" />
<bk-button
theme="primary" class="submit"
:disabled="!password || !confirmPassword" @click="handlePush">{{$t('提交')}}</bk-button>
Expand Down Expand Up @@ -88,17 +89,27 @@ export default {
password: '',
confirmPassword: '',
isError: false,
errorText: this.$t('两次输入的密码不一致,请重新输入'),
errorText: '',
successDialog: {
isShow: false,
title: this.$t('密码修改成功'),
},
setPasswordText: (this.$route.query.data || '').substring(1, (this.$route.query.data || '').length - 1),
// 是否rsa加密
isRsaEncrypted: false,
// 公钥
publicKey: '',
passwordRules: {
passwordMinLength: 0,
passwordMustIncludes: [],
},
isCorrectPw: false,
};
},
// mounted () {
// this.initToken()
// },
mounted() {
this.initRsa();
// this.initToken()
},
methods: {
// async initToken () {
// try {
Expand All @@ -116,16 +127,51 @@ export default {
// })
// }
// },
async initRsa() {
try {
const res = await this.$store.dispatch('password/getRsa', this.$route.query.token);
if (res.data) {
res.data.forEach((item) => {
switch (item.key) {
case 'enable_password_rsa_encrypted':
return this.isRsaEncrypted = true;
case 'password_rsa_public_key':
return this.publicKey = Base64.decode(item.value);
case 'password_min_length':
return this.passwordRules.passwordMinLength = item.value;
case 'password_must_includes':
return this.passwordRules.passwordMustIncludes = item.value;
}
});
}
} catch (e) {
console.warn(e);
}
},
async handlePush() {
try {
// 确认密码是否一致
if (this.password !== this.confirmPassword) {
this.isError = true;
this.errorText = this.$t('两次输入的密码不一致,请重新输入');
return;
}
// 校验密码规则
this.isCorrectPw = !this.$validatePassportByRules(this.password, this.passwordRules);
if (this.isCorrectPw) {
this.errorText = this.$getMessageByRules(this, this.passwordRules);
return;
}
if (this.isRsaEncrypted) {
this.password = Base64.encode(this.Rsa.rsaPublicData(this.password.trim(), this.publicKey));
this.confirmPassword = Base64.encode(this.Rsa.rsaPublicData(this.confirmPassword.trim(), this.publicKey));
} else {
this.password = Base64.encode(this.password.trim());
this.confirmPassword = Base64.encode(this.confirmPassword.trim());
}
const sureParam = {
token: this.$route.query.token,
password: Base64.encode(this.password.trim()),
password: this.password,
};
await this.$store.dispatch('password/setByToken', sureParam);
this.successDialog.isShow = true;
Expand All @@ -137,6 +183,10 @@ export default {
register() {
window.location.href = window.login_url;
},
handleFocus() {
this.isError = false;
this.isCorrectPw = false;
},
},
};
</script>
Expand Down

0 comments on commit 3f22a86

Please sign in to comment.