feat: 修改密码功能
This commit is contained in:
parent
3a8b70495a
commit
ee3ce43c8e
367
docs/superpowers/plans/2026-04-28-修改密码功能实现计划.md
Normal file
367
docs/superpowers/plans/2026-04-28-修改密码功能实现计划.md
Normal file
@ -0,0 +1,367 @@
|
||||
# 修改密码功能实现计划
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 为碳信网平台添加普通用户自助修改密码功能(txw-sso后端 + txw-mhzc-web前端)
|
||||
|
||||
**Architecture:**
|
||||
- 后端:SSO服务新增 `POST /sso/auth/changePassword` 接口,用户通过 authenticate 验证旧密码,通过 mhzc-service 的 Feign 接口更新用户密码
|
||||
- 前端:mhzc-web 新增修改密码页面(账号管理),工作台增加快捷入口,用户中心左侧菜单增加"账号管理"菜单项
|
||||
|
||||
**Tech Stack:** Java Spring Boot / Vue 2 / TDesign / Feign
|
||||
|
||||
---
|
||||
|
||||
## 涉及的变更文件
|
||||
|
||||
### 后端(txw-sso)
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `AuthService.java` | 新增 `changePassword` 接口声明 |
|
||||
| `AuthServiceImpl.java` | 实现 `changePassword` 逻辑 |
|
||||
| `AuthController.java` | 新增 `/auth/changePassword` 路由 |
|
||||
| `ChangePasswordReqVO.java` | 新建请求 VO |
|
||||
| `ChangePasswordRespVO.java` | 新建响应 VO |
|
||||
| `YhxxApi.java` (txw-sso-api) | 新增 Feign 方法 `updatePassword` |
|
||||
| `TxwMhzcYhxxbService.java` (txw-mhzc) | 新增 `updatePassword` 方法声明 |
|
||||
| `TxwMhzcYhxxbServiceImpl.java` (txw-mhzc) | 实现 `updatePassword` |
|
||||
| `TxwMhzcYhxxbMapper.xml` | 新增 updatePassword SQL |
|
||||
| `ISsoApi.java` | FeignClient name 常量(需确认mhzc服务名) |
|
||||
|
||||
### 前端(txw-mhzc-web)
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `views/gzt/index.vue` | 新增修改密码快捷入口按钮 |
|
||||
| `views/yhzx/zhanghugl/index.vue` | 新建修改密码页面 |
|
||||
| `router/routes.js` | 新增 `zhanghugl` 路由 |
|
||||
| `views/glxtSy/config.js` | 菜单配置新增"账号管理" |
|
||||
| `api/sso.js` | 新建,封装 changePassword API |
|
||||
|
||||
---
|
||||
|
||||
## 后端任务拆分
|
||||
|
||||
### Task 1: 后端 - 新建 ChangePasswordReqVO
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/pojo/vo/ChangePasswordReqVO.java`
|
||||
|
||||
- [ ] **Step 1: 创建文件**
|
||||
|
||||
```java
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Schema(description = "修改密码 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ChangePasswordReqVO {
|
||||
|
||||
@Schema(description = "旧密码(MD5加密)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "旧密码不能为空")
|
||||
private String oldPassword;
|
||||
|
||||
@Schema(description = "新密码(MD5加密)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "新密码不能为空")
|
||||
private String newPassword;
|
||||
|
||||
@Schema(description = "确认密码(MD5加密)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "确认密码不能为空")
|
||||
private String confirmPassword;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: 后端 - AuthService 新增 changePassword 接口声明
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/auth/AuthService.java`
|
||||
|
||||
在接口末尾添加:
|
||||
```java
|
||||
/**
|
||||
* 修改密码
|
||||
*
|
||||
* @param reqVO 修改密码请求
|
||||
* @return 成功返回 null
|
||||
*/
|
||||
void changePassword(ChangePasswordReqVO reqVO);
|
||||
```
|
||||
|
||||
引入 import:
|
||||
```java
|
||||
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: 后端 - AuthServiceImpl 实现 changePassword
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/auth/impl/AuthServiceImpl.java`
|
||||
|
||||
在类末尾添加实现方法:
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void changePassword(ChangePasswordReqVO reqVO) {
|
||||
// 1. 校验新密码与确认密码一致性
|
||||
if (!reqVO.getNewPassword().equals(reqVO.getConfirmPassword())) {
|
||||
throw exception(AUTH_PASSWORD_CONFIRM_MISMATCH);
|
||||
}
|
||||
|
||||
// 2. 密码复杂度校验(6-20位,字母+数字)
|
||||
if (!isValidPasswordComplexity(reqVO.getNewPassword())) {
|
||||
throw exception(AUTH_PASSWORD_COMPLEXITY_INVALID);
|
||||
}
|
||||
|
||||
// 3. 获取当前登录用户
|
||||
String userId = SecurityFrameworkUtils.getLoginUserId();
|
||||
YhxxbDTO yhxx = yhxxService.getYhxx(userId);
|
||||
|
||||
// 4. 校验新旧密码不能相同
|
||||
if (reqVO.getOldPassword().equals(reqVO.getNewPassword())) {
|
||||
throw exception(AUTH_PASSWORD_SAME_AS_OLD);
|
||||
}
|
||||
|
||||
// 5. 旧密码正确性校验
|
||||
authenticate(yhxx.getDlzh(), reqVO.getOldPassword());
|
||||
|
||||
// 6. 更新密码
|
||||
yhxxService.updatePassword(userId, reqVO.getNewPassword());
|
||||
}
|
||||
|
||||
private boolean isValidPasswordComplexity(String password) {
|
||||
if (password == null || password.length() < 6 || password.length() > 20) {
|
||||
return false;
|
||||
}
|
||||
boolean hasLetter = password.matches(".*[A-Za-z]+.*");
|
||||
boolean hasDigit = password.matches(".*[0-9]+.*");
|
||||
return hasLetter && hasDigit;
|
||||
}
|
||||
```
|
||||
|
||||
新增引入:
|
||||
```java
|
||||
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
|
||||
import com.css.txw.sso.util.SecurityFrameworkUtils;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_CONFIRM_MISMATCH;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_COMPLEXITY_INVALID;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_SAME_AS_OLD;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: 后端 - ErrorCodeConstants 新增错误码
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/constants/ErrorCodeConstants.java`
|
||||
|
||||
新增三个错误码:
|
||||
```java
|
||||
AUTH_PASSWORD_CONFIRM_MISMATCH(400, "两次输入的新密码不一致"),
|
||||
AUTH_PASSWORD_COMPLEXITY_INVALID(400, "密码长度6-20位,需包含字母和数字"),
|
||||
AUTH_PASSWORD_SAME_AS_OLD(400, "新密码不能与原密码相同"),
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 5: 后端 - AuthController 新增路由
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/controller/auth/AuthController.java`
|
||||
|
||||
在类末尾添加:
|
||||
|
||||
```java
|
||||
@PostMapping("/changePassword")
|
||||
@Operation(summary = "修改密码")
|
||||
public CommonResult<Void> changePassword(@RequestBody @Valid ChangePasswordReqVO reqVO) {
|
||||
authService.changePassword(reqVO);
|
||||
return success(null);
|
||||
}
|
||||
```
|
||||
|
||||
新增引入:
|
||||
```java
|
||||
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 后端 - YhxxService 新增 updatePassword 方法
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/yhxx/YhxxService.java`
|
||||
|
||||
末尾新增方法声明:
|
||||
```java
|
||||
void updatePassword(String yhUuid, String newPassword);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 7: 后端 - YhxxServiceImpl 实现 updatePassword(Feign调用mhzc)
|
||||
|
||||
**文件:** `txw-sso/txw-sso-service-biz/src/main/java/com/css/txw/sso/service/yhxx/impl/YhxxServiceImpl.java`
|
||||
|
||||
首先需要确认 mhzc 服务的 Feign 接口存在。如果 YhxxApi 不支持更新密码,则需要在 txw-sso-api 中新增 Feign 方法指向 mhzc 的更新密码接口。
|
||||
|
||||
步骤:
|
||||
1. 在 `txw-sso-api` 的 `YhxxApi.java` 中新增 `updatePassword` Feign 方法
|
||||
2. 在 `txw-mhzc` 的 `TxwMhzcYhxxbService` 新增 `updatePassword` 方法
|
||||
3. 在 `TxwMhzcYhxxbServiceImpl` 实现该方法
|
||||
4. 在 mapper XML 中新增 update SQL
|
||||
5. 在 `YhxxServiceImpl` 中调用该 Feign 接口
|
||||
|
||||
**YhxxApi.java (txw-sso-api) 新增:**
|
||||
```java
|
||||
@PostMapping("/mhzc/user/updatePassword")
|
||||
@Operation(summary = "更新用户密码")
|
||||
CommonResult<String> updatePassword(@RequestParam("yhUuid") String yhUuid, @RequestParam("dlmm") String dlmm);
|
||||
```
|
||||
|
||||
**TxwMhzcYhxxbService.java 新增:**
|
||||
```java
|
||||
String updatePassword(String yhUuid, String dlmm);
|
||||
```
|
||||
|
||||
**TxwMhzcYhxxbServiceImpl.java 新增:**
|
||||
```java
|
||||
@Override
|
||||
public String updatePassword(String yhUuid, String dlmm) {
|
||||
TxwMhzcYhxxbDO yhxxbDO = new TxwMhzcYhxxbDO();
|
||||
yhxxbDO.setYhUuid(yhUuid);
|
||||
yhxxbDO.setDlmm(dlmm);
|
||||
this.updateById(yhxxbDO);
|
||||
return "success";
|
||||
}
|
||||
```
|
||||
|
||||
**TxwMhzcYhxxbMapper.xml 新增:**
|
||||
```xml
|
||||
<update id="updatePassword">
|
||||
UPDATE txw_mhzc_yhxxb SET dlmm = #{dlmm} WHERE yh_uuid = #{yhUuid}
|
||||
</update>
|
||||
```
|
||||
|
||||
**YhxxServiceImpl.java 实现:**
|
||||
```java
|
||||
@Resource
|
||||
private YhxxApi yhxxApi;
|
||||
|
||||
@Override
|
||||
public void updatePassword(String yhUuid, String newPassword) {
|
||||
yhxxApi.updatePassword(yhUuid, newPassword);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 前端任务拆分(txw-mhzc-web)
|
||||
|
||||
### Task 8: 前端 - 新建 api/sso.js
|
||||
|
||||
**文件:** `txw-mhzc-web/src/pages/index/api/sso.js`
|
||||
|
||||
```js
|
||||
import { fetchSso } from '@/core/request';
|
||||
|
||||
export const changePassword = (params) => {
|
||||
return fetchSso({
|
||||
url: '/sso/auth/changePassword',
|
||||
data: JSON.stringify(params),
|
||||
method: 'post',
|
||||
loading: true,
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 9: 前端 - 新建修改密码页面
|
||||
|
||||
**文件:** `txw-mhzc-web/src/pages/index/views/yhzx/zhanghugl/index.vue`
|
||||
|
||||
页面元素:
|
||||
- 三个密码输入框(旧密码、新密码、确认密码)
|
||||
- 确认按钮
|
||||
- 密码格式提示文字
|
||||
|
||||
校验逻辑:
|
||||
1. 旧密码、新密码、确认密码不能为空
|
||||
2. 新密码长度6-20位,需包含字母和数字(提示:密码长度6-20位,需包含字母和数字)
|
||||
3. 新密码与确认密码一致性(提示:两次输入的新密码不一致)
|
||||
4. 提交后调用 changePassword API
|
||||
5. 成功提示"密码修改成功",可跳转回工作台
|
||||
|
||||
样式参考现有的登录页面,使用 TDesign 组件库。
|
||||
|
||||
---
|
||||
|
||||
### Task 10: 前端 - 路由配置新增 zhanghugl
|
||||
|
||||
**文件:** `txw-mhzc-web/src/pages/index/router/routes.js`
|
||||
|
||||
在 `yhzx` 的 children 数组中新增:
|
||||
```js
|
||||
{ path: 'zhanghugl', component: zhanghugl, name: 'zhanghugl', meta: { title: '账号管理' } }
|
||||
```
|
||||
|
||||
新增 zhanghugl 路由函数:
|
||||
```js
|
||||
function zhanghugl() {
|
||||
return import('@/pages/index/views/yhzx/zhanghugl/index.vue');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 11: 前端 - 菜单配置新增"账号管理"
|
||||
|
||||
**文件:** `txw-mhzc-web/src/pages/index/views/glxtSy/config.js`
|
||||
|
||||
在 `menuList` 数组中新增一项:
|
||||
```js
|
||||
{
|
||||
value: 'zhanghugl',
|
||||
title: '账号管理',
|
||||
icon: 'password',
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 12: 前端 - 工作台新增修改密码快捷入口
|
||||
|
||||
**文件:** `txw-mhzc-web/src/pages/index/views/gzt/index.vue`
|
||||
|
||||
在快捷操作区域新增按钮:
|
||||
```html
|
||||
<t-button theme="primary" variant="outline" @click="$router.push('/yhzx/zhanghugl')">
|
||||
修改密码
|
||||
</t-button>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 任务执行顺序
|
||||
|
||||
建议按以下顺序执行:
|
||||
|
||||
1. Task 1 - 新建 ChangePasswordReqVO
|
||||
2. Task 4 - 新增错误码
|
||||
3. Task 6 - YhxxService 新增 updatePassword
|
||||
4. Task 7 - YhxxServiceImpl + Feign + MHZC 实现
|
||||
5. Task 2 - AuthService 新增 changePassword
|
||||
6. Task 3 - AuthServiceImpl 实现
|
||||
7. Task 5 - AuthController 新增路由
|
||||
8. Task 8 - 前端 API 新建
|
||||
9. Task 9 - 前端页面新建
|
||||
10. Task 10 - 路由配置
|
||||
11. Task 11 - 菜单配置
|
||||
12. Task 12 - 工作台入口
|
||||
147
docs/superpowers/specs/2026-04-28-修改密码功能设计.md
Normal file
147
docs/superpowers/specs/2026-04-28-修改密码功能设计.md
Normal file
@ -0,0 +1,147 @@
|
||||
# 修改密码功能设计
|
||||
|
||||
## 1. 概述
|
||||
|
||||
为碳信网平台添加普通用户自助修改密码功能,采用前后端分离架构。
|
||||
|
||||
- **普通用户修改密码**:位于 `txw-mhzc`(用户中心),入口在个人中心左侧菜单
|
||||
- **管理员重置密码**:已存在于 `txw-yygl`,无需改动
|
||||
|
||||
---
|
||||
|
||||
## 2. 后端接口
|
||||
|
||||
### 2.1 新增接口
|
||||
|
||||
**POST `/sso/auth/changePassword`**
|
||||
|
||||
请求体:
|
||||
```json
|
||||
{
|
||||
"oldPassword": "MD5加密字符串",
|
||||
"newPassword": "MD5加密字符串",
|
||||
"confirmPassword": "MD5加密字符串"
|
||||
}
|
||||
```
|
||||
|
||||
响应(统一 `CommonResult`):
|
||||
```json
|
||||
{
|
||||
"code": 1,
|
||||
"data": null,
|
||||
"msg": "密码修改成功"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 密码复杂度规则
|
||||
|
||||
**中等级别**:
|
||||
- 长度:6-20 位
|
||||
- 必须包含:字母 + 数字
|
||||
|
||||
### 2.3 校验流程
|
||||
|
||||
1. **格式校验**:新密码长度6-20位,需同时包含字母和数字
|
||||
2. **一致性校验**:newPassword === confirmPassword
|
||||
3. **身份校验**:authenticate(username, oldPassword) 验证旧密码正确性
|
||||
4. **防重名校验**:newPassword !== oldPassword
|
||||
|
||||
### 2.4 错误码
|
||||
|
||||
| 场景 | msg |
|
||||
|------|-----|
|
||||
| 密码格式不符 | 密码长度6-20位,需包含字母和数字 |
|
||||
| 两次密码不一致 | 两次输入的新密码不一致 |
|
||||
| 旧密码错误 | 原密码输入错误 |
|
||||
| 新旧密码相同 | 新密码不能与原密码相同 |
|
||||
|
||||
### 2.5 涉及文件
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `AuthService.java` | 新增 `changePassword` 接口声明 |
|
||||
| `AuthServiceImpl.java` | 实现 `changePassword` 逻辑 |
|
||||
| `AuthController.java` | 新增 `/auth/changePassword` 路由 |
|
||||
| `AuthLoginReqVO.java` | 建议复用或新建 `ChangePasswordReqVO` |
|
||||
|
||||
---
|
||||
|
||||
## 3. 前端页面(txw-mhzc-web)
|
||||
|
||||
### 3.1 路由
|
||||
|
||||
| 路由路径 | 组件 | 菜单标题 |
|
||||
|---------|------|---------|
|
||||
| `/yhzx/zhanghugl` | `ChangePassword.vue` | 账号管理 |
|
||||
|
||||
### 3.2 工作台入口
|
||||
|
||||
在 `txw-mhzc-web/src/pages/index/views/gzt/index.vue` 新增快捷操作按钮"修改密码",点击跳转 `/yhzx/zhanghugl`。
|
||||
|
||||
### 3.3 用户中心左侧菜单
|
||||
|
||||
在 `yhzx` 路由的 children 中新增:
|
||||
```js
|
||||
{ path: 'zhanghugl', component: zhanghugl, name: 'zhanghugl', meta: { title: '账号管理' } }
|
||||
```
|
||||
|
||||
### 3.4 修改密码页面 `ChangePassword.vue`
|
||||
|
||||
**页面元素**:
|
||||
- 旧密码输入框(密码类型)
|
||||
- 新密码输入框(密码类型)
|
||||
- 确认密码输入框(密码类型)
|
||||
- 确认按钮
|
||||
|
||||
**交互逻辑**:
|
||||
- 输入框下方实时显示密码格式提示
|
||||
- 提交前统一校验
|
||||
- 成功后给出提示并可跳转其他页面
|
||||
- 失败回显错误信息
|
||||
|
||||
### 3.5 API 调用
|
||||
|
||||
```js
|
||||
// txw-mhzc-web/src/pages/index/api/sso.js
|
||||
export const changePassword = (params) => {
|
||||
return fetchSso({
|
||||
url: '/sso/auth/changePassword',
|
||||
data: JSON.stringify(params),
|
||||
method: 'post',
|
||||
loading: true,
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
### 3.6 涉及文件
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `router/routes.js` | 新增 `zhanghugl` 路由 |
|
||||
| `views/gzt/index.vue` | 新增修改密码快捷入口 |
|
||||
| `views/yhzx/zhanghugl/index.vue` | 新建修改密码页面 |
|
||||
| `api/sso.js` | 新建,封装 changePassword API |
|
||||
|
||||
---
|
||||
|
||||
## 4. yygl 管理员重置密码(已有,无需改动)
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `txw-yygl-web/.../yhgl/index.vue` | "重置密码"按钮,调用 `resetPassword(yhUuid)` |
|
||||
| `txw-yygl-web/.../api/htgl.js` | `resetPassword` 接口已实现 |
|
||||
| `txw-mhzc/.../UserController.java` | `resetPassword` 接口已实现,重置为配置默认密码 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据库字段
|
||||
|
||||
用户表 `dlmm` 字段存储 MD5 加密后的密码。
|
||||
|
||||
---
|
||||
|
||||
## 6. 备注
|
||||
|
||||
- 旧密码传输前已在前端做 MD5 加密(与现有登录流程一致)
|
||||
- 新密码传输前在前端做 MD5 加密
|
||||
- 此设计与现有 `authenticate` 的 `isPasswordMatch` 逻辑保持一致
|
||||
@ -107,6 +107,16 @@ export function mhLogout() {
|
||||
});
|
||||
}
|
||||
|
||||
// 修改密码(用户自助)
|
||||
export function changePassword(params) {
|
||||
return fetchSso({
|
||||
headers,
|
||||
url: `${basurl}/sso/auth/changePassword`,
|
||||
data: JSON.stringify(params),
|
||||
method: 'post',
|
||||
});
|
||||
}
|
||||
|
||||
// 获取重定向地址
|
||||
export function getRedirectUri() {
|
||||
return fetchSso({
|
||||
|
||||
@ -101,6 +101,11 @@ function search() {
|
||||
return import(/* webpackChunkName: "search" */ '@/pages/index/views/search/index.vue');
|
||||
}
|
||||
|
||||
// 账号管理
|
||||
function zhanghugl() {
|
||||
return import(/* webpackChunkName: "zhanghugl" */ '@/pages/index/views/yhzx/zhanghugl/index.vue');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -177,6 +182,7 @@ export default [
|
||||
{ path: 'tfwxq', component: tfwxq, name: 'tfwxq', meta: { title: '碳服务需求' } },
|
||||
{ path: 'ggwhgl', component: newsCenter, name: 'ggwhgl', meta: { title: '消息中心' } },
|
||||
{ path: 'lsjy', component: lsjy, name: 'lsjy', meta: { title: '绿色交易' } },
|
||||
{ path: 'zhanghugl', component: zhanghugl, name: 'zhanghugl', meta: { title: '账号管理' } },
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -24,4 +24,9 @@ export const menuList = [
|
||||
icon: 'circle',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: 'zhanghugl',
|
||||
title: '账号管理',
|
||||
icon: 'password',
|
||||
},
|
||||
];
|
||||
|
||||
@ -45,7 +45,7 @@ export default {
|
||||
{ label: '消息中心', icon: 'mail', to: '/yhzx/ggwhgl', bgColor: '#FCE4EC', color: '#E91E63' },
|
||||
{ label: '我的认证', icon: 'user', to: '/yhzx/qyrenzheng', bgColor: '#E3F2FD', color: '#2196F3' },
|
||||
{ label: '账号编辑', icon: 'edit', to: '/yhzx/qyrenzheng', bgColor: '#FFF8E1', color: '#FF9800' },
|
||||
{ label: '修改密码', icon: 'lock-on', to: '/yhzx/qyrenzheng', bgColor: '#E8F5E9', color: '#4CAF50' },
|
||||
{ label: '修改密码', icon: 'lock-on', to: '/yhzx/zhanghugl', bgColor: '#E8F5E9', color: '#4CAF50' },
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
192
txw-mhzc-web/src/pages/index/views/yhzx/zhanghugl/index.vue
Normal file
192
txw-mhzc-web/src/pages/index/views/yhzx/zhanghugl/index.vue
Normal file
@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div class="change-password-page">
|
||||
<div class="page-header">
|
||||
<div class="page-title">账号管理</div>
|
||||
</div>
|
||||
<div class="page-content">
|
||||
<t-form
|
||||
ref="formRef"
|
||||
:data="formData"
|
||||
:rules="rules"
|
||||
labelWidth="120"
|
||||
@submit="onSubmit"
|
||||
class="password-form"
|
||||
>
|
||||
<t-form-item label="旧密码" name="oldPassword">
|
||||
<t-input
|
||||
v-model="formData.oldPassword"
|
||||
type="password"
|
||||
placeholder="请输入旧密码"
|
||||
clearable
|
||||
showPassword
|
||||
/>
|
||||
</t-form-item>
|
||||
|
||||
<t-form-item label="新密码" name="newPassword">
|
||||
<t-input
|
||||
v-model="formData.newPassword"
|
||||
type="password"
|
||||
placeholder="请输入新密码"
|
||||
clearable
|
||||
showPassword
|
||||
/>
|
||||
<div class="password-tip">密码长度6-20位,需包含字母和数字</div>
|
||||
</t-form-item>
|
||||
|
||||
<t-form-item label="确认密码" name="confirmPassword">
|
||||
<t-input
|
||||
v-model="formData.confirmPassword"
|
||||
type="password"
|
||||
placeholder="请再次输入新密码"
|
||||
clearable
|
||||
showPassword
|
||||
/>
|
||||
</t-form-item>
|
||||
|
||||
<t-form-item class="submit-item">
|
||||
<t-button theme="primary" type="submit" :loading="submitLoading">确认修改</t-button>
|
||||
<t-button theme="default" variant="outline" @click="onReset" style="margin-left: 12px">重置</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { changePassword } from '@/pages/index/api/login';
|
||||
import { MessagePlugin } from 'tdesign-vue';
|
||||
|
||||
export default {
|
||||
name: 'ChangePassword',
|
||||
data() {
|
||||
// 密码复杂度校验
|
||||
const validatePasswordComplexity = (value) => {
|
||||
if (!value || value.length < 6 || value.length > 20) {
|
||||
return { valid: false, message: '密码长度6-20位' };
|
||||
}
|
||||
const hasLetter = /[A-Za-z]/.test(value);
|
||||
const hasDigit = /[0-9]/.test(value);
|
||||
if (!hasLetter || !hasDigit) {
|
||||
return { valid: false, message: '需包含字母和数字' };
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 密码一致性校验
|
||||
const validateConfirmPassword = (value) => {
|
||||
if (value !== this.formData.newPassword) {
|
||||
return { valid: false, message: '两次输入的新密码不一致' };
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
return {
|
||||
formData: {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
},
|
||||
rules: {
|
||||
oldPassword: [
|
||||
{ required: true, message: '旧密码不能为空', trigger: 'blur' },
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, message: '新密码不能为空', trigger: 'blur' },
|
||||
{
|
||||
validator: validatePasswordComplexity,
|
||||
message: '密码长度6-20位,需包含字母和数字',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: '确认密码不能为空', trigger: 'blur' },
|
||||
{
|
||||
validator: validateConfirmPassword,
|
||||
message: '两次输入的新密码不一致',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
submitLoading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSubmit({ validateResult }) {
|
||||
if (validateResult !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.submitLoading = true;
|
||||
|
||||
const params = {
|
||||
oldPassword: this.formData.oldPassword,
|
||||
newPassword: this.formData.newPassword,
|
||||
confirmPassword: this.formData.confirmPassword,
|
||||
};
|
||||
|
||||
changePassword(params)
|
||||
.then((res) => {
|
||||
if (res.code === 1) {
|
||||
MessagePlugin.success('密码修改成功');
|
||||
this.onReset();
|
||||
setTimeout(() => {
|
||||
this.$router.push('/yhzx/gzt');
|
||||
}, 1500);
|
||||
} else {
|
||||
MessagePlugin.error(res.msg || '密码修改失败');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
MessagePlugin.error(err.msg || '密码修改失败');
|
||||
})
|
||||
.finally(() => {
|
||||
this.submitLoading = false;
|
||||
});
|
||||
},
|
||||
onReset() {
|
||||
this.formData = {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.change-password-page {
|
||||
padding: 24px;
|
||||
background: #fff;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 32px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 16px;
|
||||
|
||||
.page-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #1a1b24;
|
||||
}
|
||||
}
|
||||
|
||||
.page-content {
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.password-form {
|
||||
.password-tip {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 4px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.submit-item {
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -45,23 +45,31 @@ public interface IMhzcApi {
|
||||
CommonResult<List<String>> getAllUserId();
|
||||
|
||||
@PostMapping(PREFIX+"/initSessionByDid")
|
||||
@Operation(summary = "初始化用户信息")
|
||||
CommonResult<YhxxbDTO> initSessionByDid(@RequestBody YhxxReqDTO reqDTO);
|
||||
@Operation(summary = "初始化用户信息")
|
||||
CommonResult<YhxxbDTO> initSessionByDid(@RequestBody YhxxReqDTO reqDTO);
|
||||
|
||||
@PostMapping(PREFIX+"/initSessionBySfzjhm")
|
||||
@Operation(summary = "根据身份证号初始化用户信息")
|
||||
CommonResult<YhxxbDTO> initSessionBySfzjhm(@RequestBody YhxxReqDTO reqDTO);
|
||||
@Operation(summary = "根据身份证号初始化用户信息")
|
||||
CommonResult<YhxxbDTO> initSessionBySfzjhm(@RequestBody YhxxReqDTO reqDTO);
|
||||
|
||||
@PostMapping(PREFIX+"/saveYhxxByDid")
|
||||
@Operation(summary = "保存did用户信息")
|
||||
CommonResult<YhxxbDTO> saveYhxxByDid(@RequestBody YhxxbDTO yhxx);
|
||||
@Operation(summary = "保存did用户信息")
|
||||
CommonResult<YhxxbDTO> saveYhxxByDid(@RequestBody YhxxbDTO yhxx);
|
||||
|
||||
@PostMapping(QYRZ_PREFIX+"/intQyxxByDid")
|
||||
@Operation(summary = "did企业认证信息")
|
||||
CommonResult<YhxxbDTO> intQyxxByDid(@RequestBody YhxxbDTO qyxx);
|
||||
@Operation(summary = "did企业认证信息")
|
||||
CommonResult<YhxxbDTO> intQyxxByDid(@RequestBody YhxxbDTO qyxx);
|
||||
|
||||
@PostMapping(PREFIX+"/updateDid")
|
||||
@Operation(summary = "更新用户did信息")
|
||||
CommonResult<YhxxbDTO> updateDid(@RequestBody YhxxbDTO yhxx);
|
||||
@Operation(summary = "更新用户did信息")
|
||||
CommonResult<YhxxbDTO> updateDid(@RequestBody YhxxbDTO yhxx);
|
||||
|
||||
@PostMapping(PREFIX+"/updatePassword")
|
||||
@Operation(summary = "更新用户密码")
|
||||
CommonResult<String> updatePassword(@RequestBody YhxxReqDTO reqDTO);
|
||||
|
||||
@PostMapping(PREFIX+"/resetPassword")
|
||||
@Operation(summary = "重置用户密码")
|
||||
CommonResult<String> resetPassword(@RequestBody YhxxReqDTO reqDTO);
|
||||
|
||||
}
|
||||
|
||||
@ -18,4 +18,6 @@ public class YhxxReqDTO implements Serializable {
|
||||
private String scxzmx;
|
||||
private String did;
|
||||
private String sfzjhm;
|
||||
private String dlmm;
|
||||
private String oldPassword;
|
||||
}
|
||||
@ -113,10 +113,16 @@ public class UserController {
|
||||
return CommonResult.success(yhxxbService.getAllUserId());
|
||||
}
|
||||
|
||||
@GetMapping("/resetPassword")
|
||||
@Operation(summary = "用户列表")
|
||||
CommonResult<String> resetPassword(@RequestParam("yhUuid") String yhuuid){
|
||||
return CommonResult.success(yhxxbService.resetPassword(yhuuid));
|
||||
@PostMapping("/resetPassword")
|
||||
@Operation(summary = "重置密码")
|
||||
CommonResult<String> resetPassword(@RequestBody YhxxReqDTO reqDTO){
|
||||
return CommonResult.success(yhxxbService.resetPassword(reqDTO.getYhuuid(), reqDTO.getDlmm()));
|
||||
}
|
||||
|
||||
@PostMapping("/updatePassword")
|
||||
@Operation(summary = "更新密码")
|
||||
CommonResult<String> updatePassword(@RequestBody YhxxReqDTO reqDTO){
|
||||
return CommonResult.success(yhxxbService.updatePassword(reqDTO.getYhuuid(), reqDTO.getDlmm(), reqDTO.getOldPassword()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -27,8 +27,6 @@ public interface TxwMhzcYhxxbService extends IService<TxwMhzcYhxxbDO> {
|
||||
|
||||
Page<UserVO> getAllUser(UserReqVO reqVO);
|
||||
|
||||
String resetPassword(String yhuuid);
|
||||
|
||||
List<String> getAllUserId();
|
||||
|
||||
Integer lockUser(UserLockVO infoVO);
|
||||
@ -42,4 +40,8 @@ public interface TxwMhzcYhxxbService extends IService<TxwMhzcYhxxbDO> {
|
||||
YhxxbDTO saveYhxxByDid(YhxxbDTO yhxx);
|
||||
|
||||
YhxxbDTO updateDid(YhxxbDTO yhxx);
|
||||
|
||||
String updatePassword(String yhUuid, String dlmm, String oldPassword);
|
||||
|
||||
String resetPassword(String yhUuid, String dlmm);
|
||||
}
|
||||
|
||||
@ -243,14 +243,28 @@ public class TxwMhzcYhxxbServiceImpl extends ServiceImpl<TxwMhzcYhxxbMapper, Txw
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resetPassword(String yhuuid) {
|
||||
public String resetPassword(String yhuuid, String dlmm) {
|
||||
TxwMhzcYhxxbDO yhxxbDO = new TxwMhzcYhxxbDO();
|
||||
yhxxbDO.setYhUuid(yhuuid);
|
||||
yhxxbDO.setDlmm(CacheUtils.dm2mc("cs_ggzc_xtcs", "dlmm"));
|
||||
yhxxbDO.setDlmm(MD5.create().digestHex(dlmm));
|
||||
this.updateById(yhxxbDO);
|
||||
return "success";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updatePassword(String yhUuid, String dlmm, String oldPassword) {
|
||||
TxwMhzcYhxxbDO yhxxbDO = this.getById(yhUuid);
|
||||
if (yhxxbDO == null) {
|
||||
throw new RuntimeException("用户不存在");
|
||||
}
|
||||
// oldPassword已在SSO层校验过,dlmm是新密码明文,需MD5加密存储
|
||||
TxwMhzcYhxxbDO updateDO = new TxwMhzcYhxxbDO();
|
||||
updateDO.setYhUuid(yhUuid);
|
||||
updateDO.setDlmm(MD5.create().digestHex(dlmm));
|
||||
this.updateById(updateDO);
|
||||
return "success";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllUserId() {
|
||||
List<TxwMhzcYhxxbDO> allUserId = yhxxbMapper.getAllUserId();
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
package com.css.txw.sso.api.yhxx;
|
||||
|
||||
import com.css.ggzc.framework.common.pojo.CommonResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@FeignClient(name = "sso-service")
|
||||
@Tag(name = "用户信息接口")
|
||||
public interface YhxxApi {
|
||||
|
||||
@PostMapping("/sso/yhxx/getYhxx")
|
||||
@Operation(summary = "获取用户信息")
|
||||
CommonResult<String> getYhxx(@RequestParam("djxh") String djxh);
|
||||
|
||||
}
|
||||
Binary file not shown.
@ -41,5 +41,10 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode OAUTH2_SJHM_LOCK = new ErrorCode(1004019, "距离上次发送验证码不超过1分钟");
|
||||
ErrorCode OAUTH2_LOGIN_SMS_NOT_EXISTS = new ErrorCode(1004020, "验证码无效或已过期");
|
||||
|
||||
// ========== 修改密码 1-002-030-000 ==========
|
||||
ErrorCode AUTH_PASSWORD_CONFIRM_MISMATCH = new ErrorCode(1004021, "两次输入的新密码不一致");
|
||||
ErrorCode AUTH_PASSWORD_COMPLEXITY_INVALID = new ErrorCode(1004022, "密码长度6-20位,需包含字母和数字");
|
||||
ErrorCode AUTH_PASSWORD_SAME_AS_OLD = new ErrorCode(1004023, "新密码不能与原密码相同");
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ public class SsoConstants {
|
||||
|
||||
public static final String CLIENT_DEFAULT = "default";
|
||||
|
||||
public static final String SMS_CLIENT_SIGNNAME = "智贸链";
|
||||
public static final String SMS_CLIENT_SIGNNAME = "可信碳信息网";
|
||||
|
||||
public static final String SMS_TEMPLATE_CODE = "SMS_474450289";
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ import com.css.txw.sso.constants.SsoConstants;
|
||||
import com.css.txw.sso.enums.LoginLogTypeEnum;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
|
||||
import com.css.txw.sso.pojo.vo.DidBindPhoneReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SMSLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SendMsgReqVO;
|
||||
@ -144,4 +145,19 @@ public class AuthController {
|
||||
response.addCookie(cookie);
|
||||
return success(login);
|
||||
}
|
||||
|
||||
@PostMapping("/changePassword")
|
||||
@Operation(summary = "修改密码")
|
||||
public CommonResult<Void> changePassword(HttpServletRequest request, @RequestBody @Valid ChangePasswordReqVO reqVO) {
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(SsoConstants.COOKIE_TOKEN_KEY, request);
|
||||
authService.changePassword(token, reqVO);
|
||||
return success(null);
|
||||
}
|
||||
|
||||
@PostMapping("/resetPassword")
|
||||
@Operation(summary = "重置密码")
|
||||
public CommonResult<Void> resetPassword(@RequestParam("yhUuid") String yhUuid) {
|
||||
authService.resetPassword(yhUuid);
|
||||
return success(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package com.css.txw.sso.pojo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Schema(description = "修改密码 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ChangePasswordReqVO {
|
||||
|
||||
@Schema(description = "旧密码(MD5加密)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "旧密码不能为空")
|
||||
private String oldPassword;
|
||||
|
||||
@Schema(description = "新密码(MD5加密)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "新密码不能为空")
|
||||
private String newPassword;
|
||||
|
||||
@Schema(description = "确认密码(MD5加密)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "确认密码不能为空")
|
||||
private String confirmPassword;
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.css.txw.sso.service.auth;
|
||||
import com.css.txw.mhzc.pojo.YhxxbDTO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
|
||||
import com.css.txw.sso.pojo.vo.DidBindPhoneReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SMSLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SendMsgReqVO;
|
||||
@ -52,4 +53,19 @@ public interface AuthService {
|
||||
AuthLoginRespVO loginBySMS(SMSLoginReqVO reqVO);
|
||||
|
||||
AuthLoginRespVO didBindPhone(@Valid DidBindPhoneReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*
|
||||
* @param token 当前用户的访问令牌
|
||||
* @param reqVO 修改密码请求
|
||||
*/
|
||||
void changePassword(String token, ChangePasswordReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 重置密码(管理员操作,重置为默认密码)
|
||||
*
|
||||
* @param yhUuid 用户UUID
|
||||
*/
|
||||
void resetPassword(String yhUuid);
|
||||
}
|
||||
|
||||
@ -6,6 +6,9 @@ import static com.css.ggzc.framework.common.exception.util.ServiceExceptionUtil.
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_LOGIN_CAPTCHA_CODE_ERROR;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_LOGIN_PASSWORD_ERROR_LOCK;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_CONFIRM_MISMATCH;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_COMPLEXITY_INVALID;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.AUTH_PASSWORD_SAME_AS_OLD;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_LOGIN_SJHM_NOT_EXISTS;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_LOGIN_SMS_NOT_EXISTS;
|
||||
import static com.css.txw.sso.constants.ErrorCodeConstants.OAUTH2_SJHM_LOCK;
|
||||
@ -37,6 +40,7 @@ import com.css.ggzc.framework.common.util.json.JsonUtils;
|
||||
import com.css.txw.common.pojo.dto.sms.SMSResDTO;
|
||||
import com.css.txw.common.service.ISMService;
|
||||
import com.css.txw.mhzc.pojo.YhxxbDTO;
|
||||
import com.css.txw.sso.pojo.dto.session.SessionInfo;
|
||||
import com.css.txw.sso.configuration.SMSClient;
|
||||
import com.css.txw.sso.controller.thirdparty.DidController;
|
||||
import com.css.txw.sso.convert.AuthConvert;
|
||||
@ -44,6 +48,7 @@ import com.css.txw.sso.pojo.domain.oauth2.OAuth2AccessTokenDO;
|
||||
import com.css.txw.sso.pojo.domain.oauth2.OAuth2ClientDO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.AuthLoginRespVO;
|
||||
import com.css.txw.sso.pojo.vo.ChangePasswordReqVO;
|
||||
import com.css.txw.sso.pojo.vo.DidBindPhoneReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SMSLoginReqVO;
|
||||
import com.css.txw.sso.pojo.vo.SendMsgReqVO;
|
||||
@ -324,4 +329,69 @@ public class AuthServiceImpl implements AuthService {
|
||||
return String.format(PHONE_LOCK, phone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changePassword(String token, ChangePasswordReqVO reqVO) {
|
||||
// 1. 校验新密码与确认密码一致性
|
||||
if (!reqVO.getNewPassword().equals(reqVO.getConfirmPassword())) {
|
||||
throw exception(AUTH_PASSWORD_CONFIRM_MISMATCH);
|
||||
}
|
||||
|
||||
// 2. 密码复杂度校验(6-20位,字母+数字)
|
||||
if (!isValidPasswordComplexity(reqVO.getNewPassword())) {
|
||||
throw exception(AUTH_PASSWORD_COMPLEXITY_INVALID);
|
||||
}
|
||||
|
||||
// 3. 通过token解析获取当前登录用户
|
||||
log.info("changePassword token: {}", token);
|
||||
SessionInfo sessionInfo = oauth2TokenService.checkAccessToken(token);
|
||||
log.info("changePassword sessionInfo: {}", sessionInfo);
|
||||
if (sessionInfo == null) {
|
||||
log.error("changePassword token解析失败, token: {}", token);
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
// 优先使用currentYhuuid,如果为空则使用tokenInfo中的yhUuid
|
||||
String yhUuid = sessionInfo.getCurrentYhuuid();
|
||||
if (GyUtils.isNull(yhUuid)) {
|
||||
yhUuid = sessionInfo.getTokenInfo().getYhUuid();
|
||||
}
|
||||
if (GyUtils.isNull(yhUuid)) {
|
||||
yhUuid = sessionInfo.getYhxx().getYhuuid();
|
||||
}
|
||||
log.info("changePassword yhUuid from token: {}", yhUuid);
|
||||
YhxxbDTO yhxx = yhxxService.getYhxx(yhUuid);
|
||||
log.info("changePassword yhxx: {}", yhxx);
|
||||
if (yhxx == null) {
|
||||
log.error("changePassword 用户不存在, yhUuid: {}", yhUuid);
|
||||
throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
// 4. 校验新旧密码不能相同
|
||||
if (reqVO.getOldPassword().equals(reqVO.getNewPassword())) {
|
||||
throw exception(AUTH_PASSWORD_SAME_AS_OLD);
|
||||
}
|
||||
|
||||
// 5. 旧密码正确性校验
|
||||
authenticate(yhxx.getDlzh(), reqVO.getOldPassword());
|
||||
|
||||
// 6. 更新密码(SSO已验证旧密码,mhzc再次验证后更新)
|
||||
yhxxService.updatePassword(yhxx.getYhUuid(), reqVO.getNewPassword(), reqVO.getOldPassword());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPassword(String yhUuid) {
|
||||
// 获取默认密码(从配置中读取)
|
||||
String defaultPassword = CacheUtils.dm2mc("cs_ggzc_xtcs", "dlmm");
|
||||
// 调用 mhzc 更新密码
|
||||
yhxxService.resetPassword(yhUuid, defaultPassword);
|
||||
}
|
||||
|
||||
private boolean isValidPasswordComplexity(String password) {
|
||||
if (password == null || password.length() < 6 || password.length() > 20) {
|
||||
return false;
|
||||
}
|
||||
boolean hasLetter = password.matches(".*[A-Za-z]+.*");
|
||||
boolean hasDigit = password.matches(".*[0-9]+.*");
|
||||
return hasLetter && hasDigit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -41,4 +41,8 @@ public interface YhxxService {
|
||||
|
||||
YhxxbDTO updateDid(YhxxbDTO yhxx);
|
||||
|
||||
void updatePassword(String yhUuid, String newPassword, String oldPassword);
|
||||
|
||||
void resetPassword(String yhUuid, String newPassword);
|
||||
|
||||
}
|
||||
|
||||
@ -243,5 +243,22 @@ public class YhxxServiceImpl implements YhxxService {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePassword(String yhUuid, String newPassword, String oldPassword) {
|
||||
YhxxReqDTO reqDTO = new YhxxReqDTO();
|
||||
reqDTO.setYhuuid(yhUuid);
|
||||
reqDTO.setDlmm(newPassword);
|
||||
reqDTO.setOldPassword(oldPassword);
|
||||
mhzcApi.updatePassword(reqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPassword(String yhUuid, String newPassword) {
|
||||
YhxxReqDTO reqDTO = new YhxxReqDTO();
|
||||
reqDTO.setYhuuid(yhUuid);
|
||||
reqDTO.setDlmm(newPassword);
|
||||
mhzcApi.resetPassword(reqDTO);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -67,8 +67,8 @@ export const getAllUser = (params) => {
|
||||
// 重置账号密码
|
||||
export const resetPassword = (params) => {
|
||||
return fetchSso({
|
||||
url: `${basurl}/mhzc/user/resetPassword?yhUuid=${params}`,
|
||||
method: 'get',
|
||||
url: `${basurl}/sso/auth/resetPassword?yhUuid=${params}`,
|
||||
method: 'post',
|
||||
loading: true,
|
||||
headers,
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user