Token架构优化:防重放攻击清除token、防重复forceLogout、refreshToken空值防御
This commit is contained in:
@@ -20,23 +20,27 @@ public class TokenFilter implements Filter {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
/** 不需要验证的路径 */
|
||||
private static final String[] EXCLUDE_PATHS = {
|
||||
/** 不需要验证的路径(精确匹配) */
|
||||
private static final String[] EXACT_PATHS = {
|
||||
"/api/user/register",
|
||||
"/api/user/login",
|
||||
"/api/auth/refresh",
|
||||
"/api/wallet/default",
|
||||
"/api/wallet/networks",
|
||||
"/api/kline/",
|
||||
"/ws/",
|
||||
"/admin/login",
|
||||
"/uploads/",
|
||||
"/swagger-resources",
|
||||
"/v2/api-docs",
|
||||
"/webjars/",
|
||||
"/swagger-ui.html"
|
||||
};
|
||||
|
||||
/** 不需要验证的路径前缀 */
|
||||
private static final String[] PREFIX_PATHS = {
|
||||
"/api/kline/",
|
||||
"/ws/",
|
||||
"/uploads/",
|
||||
"/webjars/"
|
||||
};
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
@@ -45,9 +49,17 @@ public class TokenFilter implements Filter {
|
||||
|
||||
String uri = httpRequest.getRequestURI();
|
||||
|
||||
// 检查是否排除路径
|
||||
for (String excludePath : EXCLUDE_PATHS) {
|
||||
if (uri.contains(excludePath)) {
|
||||
// 检查是否排除路径(精确匹配)
|
||||
for (String path : EXACT_PATHS) {
|
||||
if (uri.equals(path)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否排除路径前缀
|
||||
for (String prefix : PREFIX_PATHS) {
|
||||
if (uri.startsWith(prefix)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.it.rattan.monisuo.mapper.UserMapper;
|
||||
import com.it.rattan.monisuo.util.JwtUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -30,6 +31,7 @@ public class AuthService {
|
||||
* 5. 更新数据库中的 refreshToken
|
||||
* 6. 返回新 token 对
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Map<String, String> refreshToken(String refreshToken) {
|
||||
// 1. 验证 refreshToken
|
||||
if (!JwtUtil.isValid(refreshToken)) {
|
||||
@@ -56,8 +58,14 @@ public class AuthService {
|
||||
throw new RuntimeException("账号已被禁用");
|
||||
}
|
||||
|
||||
// 验证 refreshToken 与数据库中存储的一致
|
||||
if (!refreshToken.equals(user.getRefreshToken())) {
|
||||
// 验证 refreshToken 与数据库中存储的一致(防重放攻击)
|
||||
String storedRefreshToken = user.getRefreshToken();
|
||||
if (storedRefreshToken == null || !refreshToken.equals(storedRefreshToken)) {
|
||||
// refreshToken 不匹配说明可能被窃取,清除该用户所有 token
|
||||
userMapper.update(null, new LambdaUpdateWrapper<User>()
|
||||
.eq(User::getId, user.getId())
|
||||
.set(User::getToken, null)
|
||||
.set(User::getRefreshToken, null));
|
||||
throw new RuntimeException("refreshToken不匹配,请重新登录");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user