chsm-server/chsm-web-server/src/main/java/com/sunyard/chsm/service/AppLoginService.java
2024-12-06 15:38:22 +08:00

114 lines
4.2 KiB
Java

package com.sunyard.chsm.service;
import com.sunyard.chsm.auth.AppUser;
import com.sunyard.chsm.constant.SecurityConstant;
import com.sunyard.chsm.enums.EnableStatus;
import com.sunyard.chsm.mapper.ApplicationMapper;
import com.sunyard.chsm.model.entity.Application;
import com.sunyard.chsm.param.AppTokenReq;
import com.sunyard.chsm.param.AppTokenResp;
import com.sunyard.chsm.utils.CodecUtils;
import com.sunyard.chsm.utils.gm.BCSM3Utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
/**
* @author liulu
* @since 2024/12/5
*/
@Slf4j
@Service
public class AppLoginService {
/**
* token 过期时间, 分钟
*/
@Value("${chsm.token.expireTime:720}")
private Integer tokenExpireTime;
@Resource
private ApplicationMapper applicationMapper;
public AppTokenResp getAppToken(AppTokenReq req) {
Long random = req.getRandom();
long now = System.currentTimeMillis();
Assert.isTrue(now - random <= 5 * 60 * 1000, "请求已超时");
String appKey = req.getAppKey();
Application application = applicationMapper.selectByAppKey(appKey);
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
String data = appKey + random + application.getAppSecret();
byte[] hmac = BCSM3Utils.hmac(application.getAppSecret().getBytes(), data.getBytes());
String serverHmac = CodecUtils.encodeHex(hmac);
if (!Objects.equals(req.getHmac(), serverHmac)) {
log.warn("appKey: {}, req hmac: {}, server hmac: {}", appKey, req.getHmac(), serverHmac);
throw new IllegalArgumentException("应用认证失败");
}
AppTokenResp resp = new AppTokenResp();
resp.setToken(genToken(application));
return resp;
}
private String genToken(Application app) {
Map<String, Object> claims = new HashMap<>();
claims.put("appId", app.getId());
claims.put("name", app.getName());
claims.put("serviceIds", Collections.singletonList(app.getId()));
Date now = new Date();
return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + tokenExpireTime * 60 * 1000))
.setId(UUID.randomUUID().toString())
.signWith(SignatureAlgorithm.HS512, SecurityConstant.JWT_SIGN_KEY)
.compact();
}
public AppTokenResp getAppTokenForTest(@Valid AppTokenReq req) {
// Long random = req.getRandom();
// long now = System.currentTimeMillis();
// Assert.isTrue(now - random <= 5 * 60 * 1000, "请求已超时");
Application application = applicationMapper.selectByAppKey(req.getAppKey());
Assert.isTrue(EnableStatus.ENABLED.getCode().equals(application.getStatus()), "此应用已停用");
if (!Objects.equals(req.getHmac(), application.getAppSecret())) {
log.warn("appKey: {}, req hmac: {},", req.getAppKey(), req.getHmac());
throw new IllegalArgumentException("应用认证失败");
}
AppTokenResp resp = new AppTokenResp();
resp.setToken(genToken(application));
return resp;
}
public AppUser verifyToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SecurityConstant.JWT_SIGN_KEY)
.parseClaimsJws(token)
.getBody();
AppUser user = new AppUser();
user.setAppId(claims.get("appId", Long.class));
user.setName(claims.get("name", String.class));
user.setServiceIds(claims.get("serviceIds", List.class));
return user;
}
}