渗透测试漏洞修复

This commit is contained in:
马三炮 2025-11-25 18:35:29 +08:00
parent 462a4df8af
commit 819512ea6c
5 changed files with 442 additions and 287 deletions

View File

@ -3,8 +3,10 @@ package com.bonus.auth.controller;
import com.bonus.auth.form.LoginBody; import com.bonus.auth.form.LoginBody;
import com.bonus.auth.form.RegisterBody; import com.bonus.auth.form.RegisterBody;
import com.bonus.auth.service.SysLoginService; import com.bonus.auth.service.SysLoginService;
import com.bonus.common.core.constant.Constants;
import com.bonus.common.core.constant.SecurityConstants; import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R; import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.CaptchaException;
import com.bonus.common.core.utils.JwtUtils; import com.bonus.common.core.utils.JwtUtils;
import com.bonus.common.core.utils.StringUtils; import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.redis.service.RedisService; import com.bonus.common.redis.service.RedisService;
@ -46,6 +48,22 @@ public class TokenController
// 用户登录 // 用户登录
LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword(), LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword(),
form.getType(),form.getJwtToken()); form.getType(),form.getJwtToken());
if (StringUtils.isEmpty(form.getCode()))
{
throw new CaptchaException("验证码不能为空");
}
if (StringUtils.isEmpty(form.getUuid()))
{
throw new CaptchaException("验证码已失效");
}
String verifyKey = Constants.CAPTCHA_CODE_KEY + form.getUuid();
String captcha = redisService.getCacheObject(verifyKey);
redisService.deleteObject(verifyKey);
if (!form.getCode().equalsIgnoreCase(captcha))
{
throw new CaptchaException("验证码错误");
}
// 获取登录token // 获取登录token
return R.ok(tokenService.createToken(userInfo)); return R.ok(tokenService.createToken(userInfo));
} }

View File

@ -27,6 +27,13 @@ public class LoginBody
*/ */
private String jwtToken; private String jwtToken;
private String code;
/**
* 类型 有值为app登录无需密码
*/
private String uuid;
public String getType() { public String getType() {
return type; return type;
} }
@ -65,4 +72,19 @@ public class LoginBody
this.jwtToken = jwtToken; this.jwtToken = jwtToken;
} }
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
} }

View File

@ -64,14 +64,7 @@ public class AuthFilter implements GlobalFilter, Ordered
return chain.filter(exchange); return chain.filter(exchange);
} }
String token = getToken(request); String token = getToken(request);
// 获取token中的用户ID
String userId = JwtUtils.getUserId(token);
// 获取用户当前有效的token
String currentToken = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + userId);
// 如果当前token和缓存中的token不一致说明已被挤下线
if (currentToken == null || !currentToken.equals(token)) {
return unauthorizedResponse(exchange,"您的账号已在其他设备登录");
}
if (StringUtils.isEmpty(token) ) if (StringUtils.isEmpty(token) )
{ {
@ -94,7 +87,14 @@ public class AuthFilter implements GlobalFilter, Ordered
{ {
return unauthorizedResponse(exchange, "令牌验证失败"); return unauthorizedResponse(exchange, "令牌验证失败");
} }
// 获取token中的用户ID
String userId = JwtUtils.getUserId(token);
// 获取用户当前有效的token
String currentToken = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + userId);
// 如果当前token和缓存中的token不一致说明已被挤下线
if (currentToken == null || !currentToken.equals(userkey)) {
return unauthorizedResponse(exchange,"您的账号已在其他设备登录");
}
// 设置用户信息到请求 // 设置用户信息到请求
addHeader(mutate, SecurityConstants.USER_KEY, userkey); addHeader(mutate, SecurityConstants.USER_KEY, userkey);
addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);

View File

@ -12,10 +12,21 @@ body {
#content { #content {
width: 19%; width: 19%;
height: 37%; /*height: 37%;*/
display: flex;
flex-direction: column;
align-content: center;
margin-top: 15.5%; margin-top: 15.5%;
margin-left: 57%; margin-left: 57%;
} }
.common-box {
height: 42px;
display: flex;
align-items: center;
}
.title { .title {
color: #000; color: #000;
font-size: 30px; font-size: 30px;
@ -24,33 +35,41 @@ body {
letter-spacing: 10px; letter-spacing: 10px;
text-align: center; text-align: center;
} }
.content { .content {
height: 35%; height: 35%;
margin-top: 13%; margin-top: 13%;
} }
.phoneDiv{
height: 35%; .phoneDiv, .codeDiv, .pwdDiv {
height: 40px;
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
} }
.phoneDiv > div { .phoneDiv > div {
display: inline-block; display: inline-block;
} }
.phoneDiv > .title { .phoneDiv > .title {
display: inline-block; display: inline-block;
height: 60%; height: 25px;
width: 25px; width: 25px;
background: url(../img/userName.png) no-repeat; background: url(../img/userName.png) no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
margin-top: 2%; /*margin-top: 2%;*/
margin-left: 2%; /*margin-left: 2%;*/
float: left; /*float: left;*/
margin-right: 2%;
} }
#phoneDiv { #phoneDiv {
width: 80%; /*width: 80%;*/
height: 100%; height: 100%;
margin-left: 3%; margin-left: 3%;
float: left; /*float: left;*/
flex: 1;
} }
#username { #username {
height: 95%; height: 95%;
width: 97%; width: 97%;
@ -62,32 +81,78 @@ body {
} }
.pwdDiv { .pwdDiv {
height: 35%; /*height: 35%;*/
height: 40px;
margin-top: 9%; margin-top: 9%;
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
} }
.pwdDiv > div { .pwdDiv > div {
display: inline-block; display: inline-block;
} }
.pwdDiv > .title { .pwdDiv > .title {
display: inline-block; display: inline-block;
height: 60%; height: 25px;
width: 25px; width: 25px;
background: url(../img/pwd.png) no-repeat; background: url(../img/pwd.png) no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
margin-top: 2%; /*margin-top: 2%;*/
margin-left: 2%; /*margin-left: 2%;*/
float: left; /*float: left;*/
margin-right: 2%;
} }
#pwdDiv { #pwdDiv {
width: 80%; /*width: 80%;*/
height: 100%; height: 100%;
margin-left: 3%; margin-left: 3%;
float: left; /*float: left;*/
flex: 1;
} }
.codeDiv {
/*height: 35%;*/
height: 40px;
margin-top: 9%;
background-color: rgba(255, 255, 255, 0.1);
}
.codeDiv > div {
display: inline-block;
}
.codeDiv > .title {
display: inline-block;
height: 25px;
width: 25px;
background: url(../img/pwd.png) no-repeat;
background-size: 100% 100%;
/*margin-top: 2%;*/
/*margin-left: 2%;*/
/*float: left;*/
margin-right: 2%;
}
#codeDiv {
/*width: 80%;*/
height: 100%;
margin-left: 3%;
/*float: left;*/
flex: 1;
display: flex;
}
#code-img {
height: 40px;
width: 120px;
object-fit: cover;
cursor:pointer;
}
#password { #password {
height: 95%; height: 95%;
width: 97%; width: 97%;
@ -97,10 +162,24 @@ body {
float: left; float: left;
color: #000; color: #000;
} }
#code {
height: 95%;
/*width: 97%;*/
background-color: rgba(229, 235, 241, 1);
border: 0;
outline: 0;
/*float: left;*/
color: #000;
flex: 1;
}
.func { .func {
height: 7%; height: 7%;
margin-top: 4%; margin-top: 4%;
display: flex;
} }
.func span:last-child { .func span:last-child {
color: #00367A; color: #00367A;
font-size: 13px; font-size: 13px;
@ -108,9 +187,10 @@ body {
margin-left: 64%; margin-left: 64%;
cursor: pointer; cursor: pointer;
} }
#login { #login {
height: 12.5%; height: 12.5%;
margin-top: 15%; margin-top: 10%;
background-color: #0857ba; background-color: #0857ba;
text-align: center; text-align: center;
line-height: 20px; line-height: 20px;
@ -120,6 +200,7 @@ body {
line-height: 41px; line-height: 41px;
cursor: pointer; cursor: pointer;
} }
#login:hover { #login:hover {
background-color: rgba(8, 87, 186, 0.5); background-color: rgba(8, 87, 186, 0.5);
} }

View File

@ -13,23 +13,31 @@
<div id="content"> <div id="content">
<div class="title">实名制管理系统</div> <div class="title">实名制管理系统</div>
<div class="content"> <div class="content">
<div class="phoneDiv"> <div class="common-box phoneDiv">
<div class="title"></div> <div class="title"></div>
<div id="phoneDiv"> <div id="phoneDiv">
<input id="username" name="username" type="text" placeholder="手机号"/> <input id="username" name="username" type="text" placeholder="手机号"/>
<input id="jwtToken" hidden/> <input id="jwtToken" hidden/>
</div> </div>
</div> </div>
<div class="pwdDiv"> <div class="common-box pwdDiv">
<div class="title"></div> <div class="title"></div>
<div id="pwdDiv"> <div id="pwdDiv">
<input id="password" name="password" type="password" placeholder="密码"/> <input id="password" name="password" type="password" placeholder="密码"/>
</div> </div>
</div> </div>
<div class="common-box codeDiv">
<div class="title"></div>
<div id="codeDiv">
<input id="code" name="code" type="text" placeholder="验证码"/>
<img name="yzm" id="code-img">
</div>
</div>
</div> </div>
<div class="func"> <div class="func">
<input id="jzpwd" type="checkbox" /><span style="color: #00367A; font-size: 13px; font-family: '微软雅黑'; ">记住密码</span> <input id="jzpwd" type="checkbox"/><span
style="color: #00367A; font-size: 13px; font-family: '微软雅黑'; ">记住密码</span>
<span onclick="forgetPwd()" style="color: #00367A; font-size: 13px; font-family: '微软雅黑'; ">忘记密码</span> <span onclick="forgetPwd()" style="color: #00367A; font-size: 13px; font-family: '微软雅黑'; ">忘记密码</span>
</div> </div>
@ -61,13 +69,10 @@
}); });
if (top != self) { if (top != self) {
parent.location.href = '/login.html'; parent.location.href = '/login.html';
} }
var uuid=null;
var token = localStorage.getItem("smz-token"); var token = localStorage.getItem("smz-token");
if (token != null && token.trim().length != 0) { if (token != null && token.trim().length != 0) {
$.ajax({ $.ajax({
@ -94,14 +99,16 @@
function enterBtn() { function enterBtn() {
fastLogin(); fastLogin();
} }
function login(obj) { function login(obj) {
$(obj).attr("disabled", true); $(obj).attr("disabled", true);
var username = $.trim($('#username').val()); var username = $.trim($('#username').val());
var password = $.trim($('#password').val()); var password = $.trim($('#password').val());
var jwtToken = $.trim($('#jwtToken').val()); var jwtToken = $.trim($('#jwtToken').val());
var code = $.trim($('#code').val());
var jzpwd = $("#jzpwd").prop("checked"); // 是否记住密码 var jzpwd = $("#jzpwd").prop("checked"); // 是否记住密码
if (username == "" || password == "") { if (username == "" || password == "" || code == "") {
$("#info").html('手机号或者密码不能为空'); $("#info").html('手机号或者密码或者验证码不能为空');
$(obj).attr("disabled", false); $(obj).attr("disabled", false);
} else { } else {
$.ajax({ $.ajax({
@ -111,7 +118,10 @@
data: JSON.stringify({ data: JSON.stringify({
"username": encryptRsa(username), "username": encryptRsa(username),
"password": encryptRsa(password), "password": encryptRsa(password),
"jwtToken" : jwtToken "jwtToken": jwtToken,
'code': code,
"uuid":uuid
}), }),
success: function (data) { success: function (data) {
if (data.code == '200') { if (data.code == '200') {
@ -156,6 +166,7 @@
} else { } else {
$("#info").html(data.msg); $("#info").html(data.msg);
$(obj).attr("disabled", false); $(obj).attr("disabled", false);
getCodeImgFun();
} }
}, },
error: function (xhr, textStatus, errorThrown) { error: function (xhr, textStatus, errorThrown) {
@ -163,6 +174,7 @@
var response = JSON.parse(msg); var response = JSON.parse(msg);
$("#info").html(response.message); $("#info").html(response.message);
$(obj).attr("disabled", false); $(obj).attr("disabled", false);
getCodeImgFun();
} }
}); });
@ -237,7 +249,8 @@
function GetQueryString(name) { function GetQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg); var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null; if (r != null) return unescape(r[2]);
return null;
} }
//禁用 F12、鼠标右键 //禁用 F12、鼠标右键
@ -263,5 +276,26 @@
event.preventDefault() event.preventDefault()
}) })
} }
// 获取图形验证码
function getCodeImgFun() {
$.ajax({
type: 'get',
url: DATA_URL + '/code',
async: false,
success: function (data) {
console.log(data, '获取的验证码')
$('#code-img').attr('src', `data:image/gif;base64,${data.img}`)
uuid = data.uuid;
}
});
}
getCodeImgFun()
$('#code-img').click(() => {
getCodeImgFun()
})
</script> </script>
</html> </html>