package com.tourguide.security; import com.tourguide.config.properties.JwtProperties; import com.tourguide.modules.user.domain.ClientType; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; import java.security.Key; import java.util.Date; import java.util.UUID; @Service public class JwtTokenService { private final JwtProperties properties; private final Key signingKey; public JwtTokenService(JwtProperties properties) { this.properties = properties; this.signingKey = Keys.hmacShaKeyFor(properties.getSecret().getBytes(StandardCharsets.UTF_8)); } /** Token 同时写入 clientType,服务端据此阻止后台端与小程序端交叉访问。 */ public String createToken(Long userId, String username, String authority, ClientType clientType) { Date now = new Date(); return Jwts.builder() .setIssuer(properties.getIssuer()) .setSubject(String.valueOf(userId)) .setId(UUID.randomUUID().toString()) .setIssuedAt(now) .setExpiration(new Date(now.getTime() + properties.getExpirationSeconds() * 1000L)) .claim("username", username) .claim("role", authority) .claim("clientType", clientType.name()) .signWith(signingKey) .compact(); } public TokenPayload parse(String token) { Claims claims = Jwts.parserBuilder().setSigningKey(signingKey).requireIssuer(properties.getIssuer()).build() .parseClaimsJws(token).getBody(); return new TokenPayload( Long.valueOf(claims.getSubject()), claims.get("username", String.class), claims.get("role", String.class), ClientType.valueOf(claims.get("clientType", String.class)), claims.getId()); } public long getExpirationSeconds() { return properties.getExpirationSeconds(); } }