mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-11-04 09:01:37 +08:00 
			
		
		
		
	新增:新增修改密码功能,并优化部分以往代码
This commit is contained in:
		@@ -0,0 +1,33 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package top.charles7c.cnadmin.common.consts;
 | 
			
		||||
 | 
			
		||||
import lombok.AccessLevel;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author Charles7c
 | 
			
		||||
 * @since 2023/1/10 20:06
 | 
			
		||||
 */
 | 
			
		||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
 | 
			
		||||
public class RegExpConstants {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码正则(必须包含字母和数字的组合,可以使用特殊字符,长度在6-32之间)
 | 
			
		||||
     */
 | 
			
		||||
    public static final String PASSWORD = "^(?=.*\\d)(?=.*[a-z]).{6,32}$";
 | 
			
		||||
}
 | 
			
		||||
@@ -23,6 +23,9 @@ import cn.hutool.core.codec.Base64;
 | 
			
		||||
import cn.hutool.crypto.SecureUtil;
 | 
			
		||||
import cn.hutool.crypto.asymmetric.KeyType;
 | 
			
		||||
 | 
			
		||||
import top.charles7c.cnadmin.common.config.properties.RsaProperties;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.validate.ValidationUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 加密/解密工具类
 | 
			
		||||
 *
 | 
			
		||||
@@ -45,6 +48,19 @@ public class SecureUtils {
 | 
			
		||||
        return Base64.encode(SecureUtil.rsa(null, publicKey).encrypt(data, KeyType.PublicKey));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 私钥解密
 | 
			
		||||
     *
 | 
			
		||||
     * @param data
 | 
			
		||||
     *            要解密的内容(Base64 加密过)
 | 
			
		||||
     * @return 解密后的内容
 | 
			
		||||
     */
 | 
			
		||||
    public static String decryptByRsaPrivateKey(String data) {
 | 
			
		||||
        String privateKey = RsaProperties.PRIVATE_KEY;
 | 
			
		||||
        ValidationUtils.exIfBlank(privateKey, "请配置 RSA 私钥");
 | 
			
		||||
        return decryptByRsaPrivateKey(data, privateKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 私钥解密
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -44,9 +44,9 @@ public class LoginRequest implements Serializable {
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码
 | 
			
		||||
     * 密码(加密后)
 | 
			
		||||
     */
 | 
			
		||||
    @Schema(description = "密码")
 | 
			
		||||
    @Schema(description = "密码(加密后)")
 | 
			
		||||
    @NotBlank(message = "密码不能为空")
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package top.charles7c.cnadmin.system.model.request;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 修改密码信息
 | 
			
		||||
 *
 | 
			
		||||
 * @author Charles7c
 | 
			
		||||
 * @since 2023/1/9 23:28
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@Schema(description = "修改密码信息")
 | 
			
		||||
public class UpdatePasswordRequest implements Serializable {
 | 
			
		||||
 | 
			
		||||
    private static final long serialVersionUID = 1L;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 当前密码(加密后)
 | 
			
		||||
     */
 | 
			
		||||
    @Schema(description = "当前密码(加密后)")
 | 
			
		||||
    @NotBlank(message = "当前密码不能为空")
 | 
			
		||||
    private String oldPassword;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 新密码(加密后)
 | 
			
		||||
     */
 | 
			
		||||
    @Schema(description = "新密码(加密后)")
 | 
			
		||||
    @NotBlank(message = "新密码不能为空")
 | 
			
		||||
    private String newPassword;
 | 
			
		||||
}
 | 
			
		||||
@@ -55,4 +55,16 @@ public interface UserService {
 | 
			
		||||
     *            用户信息
 | 
			
		||||
     */
 | 
			
		||||
    void update(SysUser user);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改密码
 | 
			
		||||
     *
 | 
			
		||||
     * @param oldPassword
 | 
			
		||||
     *            当前密码
 | 
			
		||||
     * @param newPassword
 | 
			
		||||
     *            新密码
 | 
			
		||||
     * @param userId
 | 
			
		||||
     *            用户 ID
 | 
			
		||||
     */
 | 
			
		||||
    void updatePassword(String oldPassword, String newPassword, Long userId);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
package top.charles7c.cnadmin.system.service.impl;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
 | 
			
		||||
@@ -34,8 +35,10 @@ import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import top.charles7c.cnadmin.common.config.properties.LocalStorageProperties;
 | 
			
		||||
import top.charles7c.cnadmin.common.model.dto.LoginUser;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.FileUtils;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.SecureUtils;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.helper.LoginHelper;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.validate.ValidationUtils;
 | 
			
		||||
import top.charles7c.cnadmin.system.mapper.UserMapper;
 | 
			
		||||
import top.charles7c.cnadmin.system.model.entity.SysUser;
 | 
			
		||||
import top.charles7c.cnadmin.system.service.UserService;
 | 
			
		||||
@@ -91,9 +94,43 @@ public class UserServiceImpl implements UserService {
 | 
			
		||||
        userMapper.updateById(user);
 | 
			
		||||
 | 
			
		||||
        // 更新登录用户信息
 | 
			
		||||
        SysUser sysUser = userMapper.selectById(user.getUserId());
 | 
			
		||||
        SysUser sysUser = this.getById(user.getUserId());
 | 
			
		||||
        LoginUser loginUser = LoginHelper.getLoginUser();
 | 
			
		||||
        BeanUtil.copyProperties(sysUser, loginUser);
 | 
			
		||||
        LoginHelper.updateLoginUser(loginUser);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public void updatePassword(String oldPassword, String newPassword, Long userId) {
 | 
			
		||||
        SysUser sysUser = this.getById(userId);
 | 
			
		||||
        ValidationUtils.exIfNotEqual(sysUser.getPassword(), SecureUtils.md5Salt(oldPassword, userId.toString()),
 | 
			
		||||
            "当前密码错误");
 | 
			
		||||
 | 
			
		||||
        // 更新密码和密码重置时间
 | 
			
		||||
        LocalDateTime now = LocalDateTime.now();
 | 
			
		||||
        userMapper.update(null,
 | 
			
		||||
            new LambdaUpdateWrapper<SysUser>()
 | 
			
		||||
                .set(SysUser::getPassword, SecureUtils.md5Salt(newPassword, userId.toString()))
 | 
			
		||||
                .set(SysUser::getPwdResetTime, now).eq(SysUser::getUserId, userId));
 | 
			
		||||
 | 
			
		||||
        // 更新登录用户信息
 | 
			
		||||
        LoginUser loginUser = LoginHelper.getLoginUser();
 | 
			
		||||
        loginUser.setPwdResetTime(now);
 | 
			
		||||
        LoginHelper.updateLoginUser(loginUser);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据 ID 查询
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId
 | 
			
		||||
     *            用户 ID
 | 
			
		||||
     * @return 用户信息
 | 
			
		||||
     */
 | 
			
		||||
    private SysUser getById(Long userId) {
 | 
			
		||||
        ValidationUtils.exIfNull(userId, "用户不存在");
 | 
			
		||||
        SysUser sysUser = userMapper.selectById(userId);
 | 
			
		||||
        ValidationUtils.exIfNull(sysUser, String.format("ID为 [%s] 的用户已不存在", userId));
 | 
			
		||||
        return sysUser;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,4 +19,12 @@ export interface UpdateBasicInfoReq {
 | 
			
		||||
}
 | 
			
		||||
export function updateBasicInfo(req: UpdateBasicInfoReq) {
 | 
			
		||||
  return axios.patch('/system/user/center/basic/info', req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface UpdatePasswordReq {
 | 
			
		||||
  oldPassword: string;
 | 
			
		||||
  newPassword: string;
 | 
			
		||||
}
 | 
			
		||||
export function updatePassword(req: UpdatePasswordReq) {
 | 
			
		||||
  return axios.patch('/system/user/center/password', req);
 | 
			
		||||
}
 | 
			
		||||
@@ -105,9 +105,9 @@
 | 
			
		||||
  const loginConfig = useStorage('login-config', {
 | 
			
		||||
    rememberMe: true,
 | 
			
		||||
    username: 'admin', // 演示默认值
 | 
			
		||||
    password: '123456', // 演示默认值
 | 
			
		||||
    password: 'admin123', // 演示默认值
 | 
			
		||||
    // username: !debug ? '' : 'admin', // 演示默认值
 | 
			
		||||
    // password: !debug ? '' : '123456', // 演示默认值
 | 
			
		||||
    // password: !debug ? '' : 'admin123', // 演示默认值
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const loginForm = reactive({
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
      <a-input
 | 
			
		||||
        v-model="formData.username"
 | 
			
		||||
        :placeholder="$t('userCenter.basicInfo.placeholder.username')"
 | 
			
		||||
        size="large"
 | 
			
		||||
        max-length="50"
 | 
			
		||||
      />
 | 
			
		||||
    </a-form-item>
 | 
			
		||||
@@ -35,6 +36,7 @@
 | 
			
		||||
      <a-input
 | 
			
		||||
        v-model="formData.nickname"
 | 
			
		||||
        :placeholder="$t('userCenter.basicInfo.placeholder.nickname')"
 | 
			
		||||
        size="large"
 | 
			
		||||
        max-length="32"
 | 
			
		||||
      />
 | 
			
		||||
    </a-form-item>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,85 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <a-modal v-model:visible="updatePasswordVisible" :title="$t('userCenter.SecuritySettings.form.password.modal.title')" @cancel="handleCancelUpdatePassword" @before-ok="handleBeforeOkUpdatePassword">
 | 
			
		||||
    <a-form
 | 
			
		||||
      ref="formPasswordRef"
 | 
			
		||||
      :model="formPasswordData"
 | 
			
		||||
    >
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        field="oldPassword"
 | 
			
		||||
        :rules="{ required: true, message: $t('userCenter.SecuritySettings.form.password.oldPassword.placeholder') }"
 | 
			
		||||
        :validate-trigger="['change', 'blur']"
 | 
			
		||||
        :label="$t('userCenter.SecuritySettings.form.password.oldPassword.label')"
 | 
			
		||||
      >
 | 
			
		||||
        <a-input-password
 | 
			
		||||
          v-model="formPasswordData.oldPassword"
 | 
			
		||||
          :placeholder="$t('userCenter.SecuritySettings.form.password.oldPassword.placeholder')"
 | 
			
		||||
          size="large"
 | 
			
		||||
          allow-clear
 | 
			
		||||
          max-length="50"
 | 
			
		||||
        >
 | 
			
		||||
        </a-input-password>
 | 
			
		||||
      </a-form-item>
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        field="newPassword"
 | 
			
		||||
        :rules="[
 | 
			
		||||
          {
 | 
			
		||||
            required: true,
 | 
			
		||||
            message: $t('userCenter.SecuritySettings.form.password.error.newPassword.required'),
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            match: /^(?=.*\d)(?=.*[a-z]).{6,32}$/,
 | 
			
		||||
            message: $t('userCenter.SecuritySettings.form.password.newPassword.placeholder')
 | 
			
		||||
          }
 | 
			
		||||
        ]"
 | 
			
		||||
        :validate-trigger="['change', 'blur']"
 | 
			
		||||
        :label="$t('userCenter.SecuritySettings.form.password.newPassword.label')"
 | 
			
		||||
      >
 | 
			
		||||
        <a-input-password
 | 
			
		||||
          v-model="formPasswordData.newPassword"
 | 
			
		||||
          :placeholder="$t('userCenter.SecuritySettings.form.password.newPassword.placeholder')"
 | 
			
		||||
          size="large"
 | 
			
		||||
          allow-clear
 | 
			
		||||
          max-length="50"
 | 
			
		||||
        >
 | 
			
		||||
        </a-input-password>
 | 
			
		||||
      </a-form-item>
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        field="rePassword"
 | 
			
		||||
        :rules="[
 | 
			
		||||
          {
 | 
			
		||||
            required: true,
 | 
			
		||||
            message: $t('userCenter.SecuritySettings.form.password.rePassword.placeholder'),
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            validator: (value, callback) => {
 | 
			
		||||
              if (value !== formPasswordData.newPassword) {
 | 
			
		||||
                callback($t('userCenter.SecuritySettings.form.password.error.rePassword.notequal'))
 | 
			
		||||
              } else {
 | 
			
		||||
                callback()
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        ]"
 | 
			
		||||
        :validate-trigger="['change', 'blur']"
 | 
			
		||||
        :label="$t('userCenter.SecuritySettings.form.password.rePassword.label')"
 | 
			
		||||
      >
 | 
			
		||||
        <a-input-password
 | 
			
		||||
          v-model="formPasswordData.rePassword"
 | 
			
		||||
          :placeholder="$t('userCenter.SecuritySettings.form.password.rePassword.placeholder')"
 | 
			
		||||
          size="large"
 | 
			
		||||
          allow-clear
 | 
			
		||||
          max-length="50"
 | 
			
		||||
        >
 | 
			
		||||
        </a-input-password>
 | 
			
		||||
      </a-form-item>
 | 
			
		||||
    </a-form>
 | 
			
		||||
  </a-modal>
 | 
			
		||||
  <a-list :bordered="false">
 | 
			
		||||
    <a-list-item>
 | 
			
		||||
      <a-list-item-meta>
 | 
			
		||||
        <template #avatar>
 | 
			
		||||
          <a-typography-paragraph>
 | 
			
		||||
            {{ $t('userCenter.SecuritySettings.form.label.password') }}
 | 
			
		||||
            {{ $t('userCenter.SecuritySettings.label.password') }}
 | 
			
		||||
          </a-typography-paragraph>
 | 
			
		||||
        </template>
 | 
			
		||||
        <template #description>
 | 
			
		||||
@@ -17,7 +92,7 @@
 | 
			
		||||
            </a-typography-paragraph>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="operation">
 | 
			
		||||
            <a-link>
 | 
			
		||||
            <a-link @click="handleClickUpdatePassword">
 | 
			
		||||
              {{ $t('userCenter.SecuritySettings.button.update') }}
 | 
			
		||||
            </a-link>
 | 
			
		||||
          </div>
 | 
			
		||||
@@ -76,9 +151,49 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
  import { reactive, ref } from 'vue';
 | 
			
		||||
  import { useLoginStore } from '@/store';
 | 
			
		||||
  import { FormInstance } from "@arco-design/web-vue/es/form";
 | 
			
		||||
  import useLoading from "@/hooks/loading";
 | 
			
		||||
  import { updatePassword } from "@/api/system/user-center";
 | 
			
		||||
  import { Message } from "@arco-design/web-vue";
 | 
			
		||||
  import { encryptByRsa } from "@/utils/encrypt";
 | 
			
		||||
 | 
			
		||||
  const { loading, setLoading } = useLoading();
 | 
			
		||||
  const loginStore = useLoginStore();
 | 
			
		||||
  const formPasswordRef = ref<FormInstance>();
 | 
			
		||||
  const updatePasswordVisible = ref(false);
 | 
			
		||||
  const formPasswordData = reactive({
 | 
			
		||||
    oldPassword: '',
 | 
			
		||||
    newPassword: '',
 | 
			
		||||
    rePassword: '',
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const handleClickUpdatePassword = () => {
 | 
			
		||||
    updatePasswordVisible.value = true;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleBeforeOkUpdatePassword = async () => {
 | 
			
		||||
    const errors = await formPasswordRef.value?.validate();
 | 
			
		||||
    if (loading.value) return false;
 | 
			
		||||
    if (errors) return false;
 | 
			
		||||
    setLoading(true);
 | 
			
		||||
    try {
 | 
			
		||||
      const res = await updatePassword({
 | 
			
		||||
        oldPassword: encryptByRsa(formPasswordData.oldPassword) || '',
 | 
			
		||||
        newPassword: encryptByRsa(formPasswordData.newPassword) || '',
 | 
			
		||||
      });
 | 
			
		||||
      if (res.success) Message.success(res.msg);
 | 
			
		||||
    } finally {
 | 
			
		||||
      setLoading(false);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleCancelUpdatePassword = () => {
 | 
			
		||||
    updatePasswordVisible.value = false;
 | 
			
		||||
    formPasswordRef.value?.resetFields()
 | 
			
		||||
  };
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="less">
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,19 @@ export default {
 | 
			
		||||
  'userCenter.reset': 'Reset',
 | 
			
		||||
 | 
			
		||||
  'userCenter.tab.securitySettings': 'Security Settings',
 | 
			
		||||
  'userCenter.SecuritySettings.form.label.password': 'Login Password',
 | 
			
		||||
  'userCenter.SecuritySettings.label.password': 'Login Password',
 | 
			
		||||
  'userCenter.SecuritySettings.placeholder.password':
 | 
			
		||||
    'You have not set a password yet. The password must contain at least six letters, digits, and special characters except Spaces.',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.modal.title': 'Update login password',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.oldPassword.label': 'Old password',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.oldPassword.placeholder': 'Please enter old password',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.newPassword.label': 'New password',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.error.newPassword.required': 'Please enter new password',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.newPassword.placeholder': 'Password contains 6 to 32 digits and letters',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.rePassword.label': 'Confirm password',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.rePassword.placeholder': 'Please enter new password again',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.error.rePassword.notequal': 'Two passwords are different',
 | 
			
		||||
 | 
			
		||||
  'userCenter.SecuritySettings.form.label.phone': 'Phone',
 | 
			
		||||
  'userCenter.SecuritySettings.placeholder.phone':
 | 
			
		||||
    'You have not set a phone yet. The phone binding can be used to retrieve passwords and receive notifications and SMS login.',
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,19 @@ export default {
 | 
			
		||||
  'userCenter.reset': '重置',
 | 
			
		||||
 | 
			
		||||
  'userCenter.tab.securitySettings': '安全设置',
 | 
			
		||||
  'userCenter.SecuritySettings.form.label.password': '登录密码',
 | 
			
		||||
  'userCenter.SecuritySettings.label.password': '登录密码',
 | 
			
		||||
  'userCenter.SecuritySettings.placeholder.password':
 | 
			
		||||
    '您暂未设置密码,密码至少6位字符,支持数字、字母和除空格外的特殊字符。',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.modal.title': '修改登录密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.oldPassword.label': '当前密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.oldPassword.placeholder': '请输入当前密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.newPassword.label': '新密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.error.newPassword.required': '请输入新密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.newPassword.placeholder': '密码长度6到32位,同时包含数字和字母',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.rePassword.label': '确认新密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.rePassword.placeholder': '请再次输入新密码',
 | 
			
		||||
  'userCenter.SecuritySettings.form.password.error.rePassword.notequal': '两次输入的密码不一致',
 | 
			
		||||
 | 
			
		||||
  'userCenter.SecuritySettings.form.label.phone': '安全手机',
 | 
			
		||||
  'userCenter.SecuritySettings.placeholder.phone':
 | 
			
		||||
    '您暂未设置手机号,绑定手机号可以用来找回密码、接收通知、短信登录等。',
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,6 @@ import top.charles7c.cnadmin.auth.model.request.LoginRequest;
 | 
			
		||||
import top.charles7c.cnadmin.auth.model.vo.LoginVO;
 | 
			
		||||
import top.charles7c.cnadmin.auth.model.vo.UserInfoVO;
 | 
			
		||||
import top.charles7c.cnadmin.auth.service.LoginService;
 | 
			
		||||
import top.charles7c.cnadmin.common.config.properties.RsaProperties;
 | 
			
		||||
import top.charles7c.cnadmin.common.model.dto.LoginUser;
 | 
			
		||||
import top.charles7c.cnadmin.common.model.vo.R;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.ExceptionUtils;
 | 
			
		||||
@@ -72,8 +71,8 @@ public class LoginController {
 | 
			
		||||
        ValidationUtils.exIfCondition(() -> !captcha.equalsIgnoreCase(loginRequest.getCaptcha()), "验证码错误");
 | 
			
		||||
 | 
			
		||||
        // 用户登录
 | 
			
		||||
        String rawPassword = ExceptionUtils
 | 
			
		||||
            .exToNull(() -> SecureUtils.decryptByRsaPrivateKey(loginRequest.getPassword(), RsaProperties.PRIVATE_KEY));
 | 
			
		||||
        String rawPassword =
 | 
			
		||||
            ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(loginRequest.getPassword()));
 | 
			
		||||
        ValidationUtils.exIfBlank(rawPassword, "密码解密失败");
 | 
			
		||||
        String token = loginService.login(loginRequest.getUsername(), rawPassword);
 | 
			
		||||
        return R.ok(new LoginVO().setToken(token));
 | 
			
		||||
 
 | 
			
		||||
@@ -30,15 +30,20 @@ import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import cn.hutool.core.io.file.FileNameUtil;
 | 
			
		||||
import cn.hutool.core.util.ReUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
 | 
			
		||||
import top.charles7c.cnadmin.common.config.properties.LocalStorageProperties;
 | 
			
		||||
import top.charles7c.cnadmin.common.consts.FileConstants;
 | 
			
		||||
import top.charles7c.cnadmin.common.consts.RegExpConstants;
 | 
			
		||||
import top.charles7c.cnadmin.common.model.vo.R;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.ExceptionUtils;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.SecureUtils;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.helper.LoginHelper;
 | 
			
		||||
import top.charles7c.cnadmin.common.util.validate.ValidationUtils;
 | 
			
		||||
import top.charles7c.cnadmin.system.model.entity.SysUser;
 | 
			
		||||
import top.charles7c.cnadmin.system.model.request.UpdateBasicInfoRequest;
 | 
			
		||||
import top.charles7c.cnadmin.system.model.request.UpdatePasswordRequest;
 | 
			
		||||
import top.charles7c.cnadmin.system.model.vo.AvatarVO;
 | 
			
		||||
import top.charles7c.cnadmin.system.service.UserService;
 | 
			
		||||
 | 
			
		||||
@@ -85,4 +90,24 @@ public class UserCenterController {
 | 
			
		||||
        userService.update(user);
 | 
			
		||||
        return R.ok("修改成功");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Operation(summary = "修改密码", description = "修改用户登录密码")
 | 
			
		||||
    @PatchMapping("/password")
 | 
			
		||||
    public R updatePassword(@Validated @RequestBody UpdatePasswordRequest updatePasswordRequest) {
 | 
			
		||||
        // 解密
 | 
			
		||||
        String rawOldPassword =
 | 
			
		||||
            ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updatePasswordRequest.getOldPassword()));
 | 
			
		||||
        ValidationUtils.exIfBlank(rawOldPassword, "当前密码解密失败");
 | 
			
		||||
        String rawNewPassword =
 | 
			
		||||
            ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updatePasswordRequest.getNewPassword()));
 | 
			
		||||
        ValidationUtils.exIfBlank(rawNewPassword, "新密码解密失败");
 | 
			
		||||
 | 
			
		||||
        // 校验
 | 
			
		||||
        ValidationUtils.exIfCondition(() -> !ReUtil.isMatch(RegExpConstants.PASSWORD, rawNewPassword),
 | 
			
		||||
            "密码长度6到32位,同时包含数字和字母");
 | 
			
		||||
 | 
			
		||||
        // 修改密码
 | 
			
		||||
        userService.updatePassword(rawOldPassword, rawNewPassword, LoginHelper.getUserId());
 | 
			
		||||
        return R.ok("修改成功");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user