# 一、需求与背景
经常会有这样的场景:
线上出bug了,我需要登录用户的账号 重现下,但是当我们登录 用户账号的时候,会问用户密码,涉及隐私,同时还会将其 踢掉线,等等一系列麻烦的操作。
那么有没有办法解决呢? 这个时候呢,万能密码出现了,有如下几点:
- 使用万能密码可以登录任何账号
- 不将别人 踢掉线
# 二、架构与思想
由于逻辑比较简单,这里只是简单说一下大概思路:
- 需要在登录的时候,优先进行万能密码判断;
- 万能密码生成的 token 不会提掉线
- 万能密码生成的 token 有效期比较短,防止引起其他问题
- 万能密码方便修改和配置
# 三、具体使用
SmartAdmin 中 万能密码记录在了 t_config
表中,key
为 super_password
;
# 四、实现原理
# 4.1、登录代码
net.lab1024.sa.admin.module.system.login.service.LoginService#login
方法
* 验证密码:
* 1、万能密码
* 2、真实密码
*/
String superPassword = EmployeeService.getEncryptPwd(configService.getConfigValue(ConfigKeyEnum.SUPER_PASSWORD));
String requestPassword = EmployeeService.getEncryptPwd(loginForm.getPassword());
if (!(superPassword.equals(requestPassword) || employeeEntity.getLoginPwd().equals(requestPassword))) {
saveLoginLog(employeeEntity, ip, userAgent, "密码错误", LoginLogResultEnum.LOGIN_FAIL);
return ResponseDTO.userErrorParam("登录名或密码错误!");
}
// 生成 登录token,保存token
Boolean superPasswordFlag = superPassword.equals(requestPassword);
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4.2、token
代码:net.lab1024.sa.common.module.support.token.TokenService
/**
* 生成Token,并存入redis
*/
public String generateToken(Long userId, String userName, UserTypeEnum userTypeEnum, LoginDeviceEnum loginDeviceEnum, Boolean superPasswordFlag) {
long nowTimeMilli = System.currentTimeMillis();
Claims jwtClaims = Jwts.claims();
jwtClaims.put(JwtConst.CLAIM_ID_KEY, userId);
jwtClaims.put(JwtConst.CLAIM_NAME_KEY, userName);
jwtClaims.put(JwtConst.CLAIM_USER_TYPE_KEY, userTypeEnum.getValue());
jwtClaims.put(JwtConst.CLAIM_DEVICE_KEY, loginDeviceEnum.getValue());
jwtClaims.put(JwtConst.CLAIM_SUPER_PASSWORD_FLAG, superPasswordFlag);
JwtBuilder jwtBuilder = Jwts.builder()
.setClaims(jwtClaims)
.setIssuedAt(new Date(nowTimeMilli))
.signWith(SignatureAlgorithm.HS512, tokenKey);
// 如果是万能密码,则不需要记录到redis中;万能密码最多半个小时有效期
if (superPasswordFlag) {
jwtBuilder.setExpiration(new Date(nowTimeMilli + (HOUR_TIME_MILLI / 2)));
return jwtBuilder.compact();
}
jwtBuilder.setExpiration(new Date(nowTimeMilli + tokenExpire * 24 * HOUR_TIME_MILLI));
String token = jwtBuilder.compact();
String redisKey = this.generateTokenRedisKey(userId, userTypeEnum.getValue(), loginDeviceEnum.getValue());
redisService.set(redisKey, token, tokenExpire * 24 * 3600);
return token;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 联系我们
1024创新实验室-主任:卓大 (opens new window),混迹于各个技术圈,研究过计算机,熟悉点 java,略懂点前端。
1024创新实验室(河南·洛阳) (opens new window) 致力于成为中原领先、国内一流的技术团队,以技术创新为驱动,合作各类项目(软件外包、技术顾问、培训等等)。
![]() | ![]() | ![]() |
加 主任 “卓大” 微信 拉你入群,一起学习 | 关注 “小镇程序员” 分享代码与生活、技术与赚钱 | 请 “1024创新实验室” 喝咖啡 支持我们的开源与分享 |