如何使用XSLT1.0/2.0的datetime验证Epoch时间及JWT exp字段
没问题,我来帮你搞定这两个问题——用datetime验证JWT的exp(Epoch时间),以及用XSLT 1.0/2.0实现这个验证逻辑。
一、用Datetime验证Epoch时间的通用思路
首先明确:JWT里的exp是UTC时区下的Epoch时间戳(从1970-01-01T00:00:00Z开始的秒数),验证逻辑核心就是比较当前UTC时间的Epoch秒数和exp值的大小:如果当前时间戳 < exp,则令牌未过期,反之则过期。
关键注意点
- 必须用UTC时间,不能用本地时间,否则会因为时区差导致验证错误。
- 如果你还想验证TTL是否符合600秒的要求,可以计算
exp - iat是否等于600(你的示例里1522945492 - 1522944892 = 600,正好符合)。
示例(以Python为例)
import datetime # 从JWT解析出的exp值 exp_timestamp = 1522945492 # 获取当前UTC时间的Epoch秒数(必须用utc,避免时区问题) current_timestamp = int(datetime.datetime.now(datetime.timezone.utc).timestamp()) # 验证过期时间 if current_timestamp < exp_timestamp: print("✅ 令牌未过期") else: print("❌ 令牌已过期") # 额外验证TTL是否为600秒 iat_timestamp = 1522944892 if exp_timestamp - iat_timestamp == 600: print("✅ TTL符合预期(600秒)") else: print("❌ TTL不符合要求")
二、XSLT 1.0/2.0实现验证逻辑
XSLT 2.0和1.0的差异很大,2.0有原生的日期时间处理能力,1.0则需要手动实现或者依赖扩展,我分开来说:
1. XSLT 2.0 实现(推荐,更简洁)
XSLT 2.0支持xs:dateTime类型和时间运算,还能直接用json-to-xml()解析JWT的JSON字符串,步骤如下:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl:template match="/"> <!-- 1. 定义JWT的JSON字符串(如果已经是XML结构可以跳过这一步) --> <xsl:variable name="jwt-json" select='"{ \"iss\": \"SOS\", \"sub\": \"SOS\", \"iat\": 1522944892, \"exp\": 1522945492, \"dfp\": \"123\" }"' /> <!-- 2. 把JSON转成XML结构 --> <xsl:variable name="jwt-xml" select="json-to-xml($jwt-json)" /> <!-- 3. 提取exp和iat字段 --> <xsl:variable name="exp" select="$jwt-xml//*[@key='exp']" /> <xsl:variable name="iat" select="$jwt-xml//*[@key='iat']" /> <!-- 4. 将exp转换为UTC日期时间 --> <xsl:variable name="exp-datetime" select="xs:dateTime('1970-01-01T00:00:00Z') + xs:dayTimeDuration(concat('PT', $exp, 'S'))" /> <!-- 5. 获取当前UTC时间 --> <xsl:variable name="current-datetime" select="current-dateTime()" /> <!-- 6. 验证过期时间 --> <xsl:choose> <xsl:when test="$current-datetime lt $exp-datetime"> <validation-result>valid</validation-result> <message>令牌未过期</message> </xsl:when> <xsl:otherwise> <validation-result>invalid</validation-result> <message>令牌已过期</message> </xsl:otherwise> </xsl:choose> <!-- 额外验证TTL是否为600秒 --> <xsl:if test="$exp - $iat = 600"> <ttl-check>pass</ttl-check> <ttl-message>TTL符合600秒要求</ttl-message> </xsl:if> <xsl:if test="$exp - $iat != 600"> <ttl-check>fail</ttl-check> <ttl-message>TTL不符合要求,应为600秒</ttl-message> </xsl:if> </xsl:template> </xsl:stylesheet>
2. XSLT 1.0 实现(需手动处理日期)
XSLT 1.0没有原生的日期时间和Epoch转换函数,所以需要手动计算当前时间的Epoch秒数,或者依赖EXSLT扩展(如果你的处理器支持,比如Saxon、libxslt)。
方法:借助EXSLT获取当前时间 + 手动转换Epoch
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date"> <xsl:template match="/"> <!-- 1. 提取exp和iat(假设JWT已转为XML结构) --> <xsl:variable name="exp" select="/jwt/exp" /> <xsl:variable name="iat" select="/jwt/iat" /> <!-- 2. 获取当前UTC时间的ISO字符串(依赖EXSLT的date:date-time()) --> <xsl:variable name="current-iso" select="date:date-time()" /> <!-- 3. 将ISO时间转换为Epoch秒数 --> <xsl:variable name="current-timestamp"> <xsl:call-template name="iso-to-epoch"> <xsl:with-param name="iso-date" select="$current-iso" /> </xsl:call-template> </xsl:variable> <!-- 4. 验证过期时间 --> <xsl:choose> <xsl:when test="$current-timestamp < $exp"> <validation-result>valid</validation-result> <message>令牌未过期</message> </xsl:when> <xsl:otherwise> <validation-result>invalid</validation-result> <message>令牌已过期</message> </xsl:otherwise> </xsl:choose> <!-- 验证TTL --> <xsl:if test="$exp - $iat = 600"> <ttl-check>pass</ttl-check> </xsl:if> </xsl:template> <!-- 自定义模板:将ISO 8601 UTC时间(如2024-05-20T12:34:56Z)转为Epoch秒数 --> <xsl:template name="iso-to-epoch"> <xsl:param name="iso-date" /> <!-- 拆分日期时间各部分 --> <xsl:variable name="year" select="substring($iso-date, 1, 4)" /> <xsl:variable name="month" select="substring($iso-date, 6, 2)" /> <xsl:variable name="day" select="substring($iso-date, 9, 2)" /> <xsl:variable name="hour" select="substring($iso-date, 12, 2)" /> <xsl:variable name="minute" select="substring($iso-date, 15, 2)" /> <xsl:variable name="second" select="substring($iso-date, 18, 2)" /> <!-- 计算1970到当前年份的总秒数(含闰年) --> <xsl:variable name="years-since-1970" select="$year - 1970" /> <xsl:variable name="leap-years" select="floor(($year - 1968) div 4) - floor(($year - 1900) div 100) + floor(($year - 1600) div 400)" /> <xsl:variable name="year-seconds" select="($years-since-1970 * 365 + $leap-years) * 86400" /> <!-- 计算当年已过月份的总天数 --> <xsl:variable name="month-days"> <xsl:choose> <xsl:when test="$month = 1">0</xsl:when> <xsl:when test="$month = 2">31</xsl:when> <xsl:when test="$month = 3">59</xsl:when> <xsl:when test="$month = 4">90</xsl:when> <xsl:when test="$month = 5">120</xsl:when> <xsl:when test="$month = 6">151</xsl:when> <xsl:when test="$month = 7">181</xsl:when> <xsl:when test="$month = 8">212</xsl:when> <xsl:when test="$month = 9">243</xsl:when> <xsl:when test="$month = 10">273</xsl:when> <xsl:when test="$month = 11">304</xsl:when> <xsl:when test="$month = 12">334</xsl:when> </xsl:choose> </xsl:variable> <!-- 闰年且月份>2时加1天 --> <xsl:variable name="leap-adjust" select="if ($year mod 4 = 0 and ($year mod 100 != 0 or $year mod 400 = 0) and $month > 2) then 1 else 0" /> <xsl:variable name="month-seconds" select="($month-days + $leap-adjust) * 86400" /> <!-- 计算当日、小时、分钟的秒数 --> <xsl:variable name="day-seconds" select="($day - 1) * 86400" /> <xsl:variable name="hour-seconds" select="$hour * 3600" /> <xsl:variable name="minute-seconds" select="$minute * 60" /> <!-- 总Epoch秒数 --> <xsl:value-of select="$year-seconds + $month-seconds + $day-seconds + $hour-seconds + $minute-seconds + $second" /> </xsl:template> </xsl:stylesheet>
注意事项
- 如果你的XSLT处理器不支持EXSLT,建议将当前Epoch时间作为参数传入样式表,这样可以避免手动计算的复杂和误差。
- 手动计算闰年的逻辑覆盖了大部分场景,但对非常古老的年份可能存在误差,适合常规业务场景。
内容的提问来源于stack exchange,提问作者Kumar_y
相关产品推荐
相关产品推荐

