This commit is contained in:
jack ning
2025-07-20 16:08:51 +08:00
parent ab233e5cbb
commit 5dbec1efd6
3 changed files with 73 additions and 27 deletions

View File

@@ -14,6 +14,8 @@
*/
package com.bytedesk.core.rbac.auth;
import java.time.ZonedDateTime;
import org.modelmapper.ModelMapper;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -117,14 +119,14 @@ public class AuthService {
UserResponse userResponse = ConvertUtils.convertToUserResponse(userDetails);
String accessToken = JwtUtils.generateJwtToken(userDetails.getUsername(), userDetails.getPlatform());
// 登录成功后将生成的accessToken同时保存到数据库中
String channel = userDetails.getChannel();
if (channel == null || channel.isEmpty()) {
// 如果UserDetailsImpl中没有client信息使用默认值
channel = ChannelEnum.WEB.name();
}
String accessToken = JwtUtils.generateJwtToken(userDetails.getUsername(), userDetails.getPlatform(), channel);
String device = userDetails.getDevice();
if (device == null || device.isEmpty()) {
@@ -143,21 +145,19 @@ public class AuthService {
.device(device)
.userUid(userDetails.getUid())
.build();
// 只有当client中含有web字样时expiresAt有效期24小时否则为365天
if (channel.toLowerCase().contains("web")) {
tokenRequest.setExpiresAt(BdDateUtils.now().plusDays(30)); // 默认30天过期
} else {
tokenRequest.setExpiresAt(BdDateUtils.now().plusDays(365)); // 其他客户端默认365天过期
}
// 使用TokenRestService来创建token它会统一处理过期时间
TokenEntity entity = modelMapper.map(tokenRequest, TokenEntity.class);
entity.setUid(uidUtils.getUid());
//
// 统一设置过期时间与JWT配置保持一致
entity.setExpiresAt(JwtUtils.calculateExpirationTime(channel));
TokenEntity savedEntity = tokenRepository.save(entity);
if (savedEntity == null) {
throw new RuntimeException("Create token failed");
}
// 手动将实体放入缓存
return AuthResponse.builder()
.accessToken(accessToken)
.user(userResponse)

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2025-05-22 15:42:28
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-07-20 15:42:31
* @LastEditTime: 2025-07-20 16:04:10
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -13,6 +13,7 @@
*/
package com.bytedesk.core.rbac.token;
import java.time.ZonedDateTime;
import java.util.Optional;
import org.modelmapper.ModelMapper;
@@ -31,6 +32,7 @@ import com.bytedesk.core.exception.NotLoginException;
import com.bytedesk.core.rbac.auth.AuthService;
import com.bytedesk.core.rbac.user.UserEntity;
import com.bytedesk.core.uid.UidUtils;
import com.bytedesk.core.utils.BdDateUtils;
import com.bytedesk.core.utils.JwtUtils;
import lombok.AllArgsConstructor;
@@ -69,7 +71,7 @@ public class TokenRestService extends BaseRestService<TokenEntity, TokenRequest,
@Override
public TokenResponse queryByUid(TokenRequest request) {
Optional<TokenEntity> optional = tokenRepository.findByUid(request.getUid());
Optional<TokenEntity> optional = findByUid(request.getUid());
if (optional.isPresent()) {
TokenEntity entity = optional.get();
return convertToResponse(entity);
@@ -102,7 +104,7 @@ public class TokenRestService extends BaseRestService<TokenEntity, TokenRequest,
// 统一设置过期时间如果请求中没有设置过期时间则使用JWT配置的过期时间
if (entity.getExpiresAt() == null) {
entity.setExpiresAt(calculateExpirationTime(request.getChannel()));
entity.setExpiresAt(JwtUtils.calculateExpirationTime(request.getChannel()));
}
TokenEntity savedEntity = save(entity);
@@ -113,13 +115,6 @@ public class TokenRestService extends BaseRestService<TokenEntity, TokenRequest,
return convertToResponse(savedEntity);
}
// 添加一个新方法来处理缓存
// @CachePut(cacheNames = "token", key = "#entity.accessToken")
// private TokenEntity cacheToken(TokenEntity entity) {
// log.debug("Manually caching token with key: {}", entity.getAccessToken());
// return entity;
// }
@Override
public TokenResponse update(TokenRequest request) {
Optional<TokenEntity> optional = findByUid(request.getUid());
@@ -196,8 +191,10 @@ public class TokenRestService extends BaseRestService<TokenEntity, TokenRequest,
if (!StringUtils.hasText(platform)) {
platform = PlatformEnum.BYTEDESK.name(); // 默认平台
}
// 生成访问令牌
return JwtUtils.generateJwtToken(username, platform);
String channel = request.getChannel();
// 生成访问令牌,传递渠道信息以设置合适的过期时间
return JwtUtils.generateJwtToken(username, platform, channel);
}
/**

View File

@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 16:21:24
* @LastEditors: jackning 270580156@qq.com
* @LastEditTime: 2025-05-30 09:54:52
* @LastEditTime: 2025-07-20 15:52:40
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
@@ -14,6 +14,7 @@
*/
package com.bytedesk.core.utils;
import java.time.ZonedDateTime;
import java.util.Date;
import javax.crypto.SecretKey;
@@ -39,20 +40,68 @@ public class JwtUtils {
/**
* https://github.com/jwtk/jjwt?tab=readme-ov-file#creating-a-jwt
* 根据渠道类型生成JWT token支持不同的过期时间
*
* @param username
* @return
* @param username 用户名
* @param platform 平台
* @param channel 渠道类型web/mobile等
* @return JWT token字符串
*/
public String generateJwtToken(String username, String platform) {
public String generateJwtToken(String username, String platform, String channel) {
JwtSubject jwtSubject = new JwtSubject(username.toLowerCase(), platform.toLowerCase());
// 根据渠道类型计算过期时间
long expirationMs = calculateExpirationMs(channel);
return Jwts.builder()
.subject(jwtSubject.toJson())
.issuedAt(new Date())
.expiration(new Date((new Date()).getTime() + Long.parseLong(getBytedeskProperties().getJwt().getExpiration())))
.expiration(new Date((new Date()).getTime() + expirationMs))
.signWith(secretKey())
.compact();
}
/**
* 根据渠道类型计算过期时间(毫秒)
*
* @param channel 渠道类型
* @return 过期时间(毫秒)
*/
private long calculateExpirationMs(String channel) {
// 获取JWT配置的过期时间毫秒
long jwtExpirationMs = Long.parseLong(getBytedeskProperties().getJwt().getExpiration());
// 根据渠道类型调整过期时间
if (channel != null && channel.toLowerCase().contains("web")) {
// Web端使用JWT配置的过期时间默认30天
return jwtExpirationMs;
} else {
// 移动端等其他客户端使用更长的过期时间365天
return 365L * 24 * 60 * 60 * 1000; // 365天转换为毫秒
}
}
/**
* 根据渠道类型计算过期时间ZonedDateTime
* 统一JWT和数据库token的过期时间处理
*
* @param channel 渠道类型
* @return ZonedDateTime 过期时间
*/
public static ZonedDateTime calculateExpirationTime(String channel) {
// 获取JWT配置的过期时间毫秒
long jwtExpirationMs = Long.parseLong(getBytedeskProperties().getJwt().getExpiration());
// 根据渠道类型调整过期时间
if (channel != null && channel.toLowerCase().contains("web")) {
// Web端使用JWT配置的过期时间默认30天
return BdDateUtils.now().plusSeconds(jwtExpirationMs / 1000);
} else {
// 移动端等其他客户端使用更长的过期时间365天
return BdDateUtils.now().plusDays(365);
}
}
public Boolean validateJwtToken(String authToken) {
try {
// 这一步会验证token的签名和过期时间如果token已过期会抛出ExpiredJwtException