我正在使用Spring引导资源服务器。身份验证服务器发出一个JWT。此JWT使用一个密钥重新编码(使用AES),在资源服务器中,我应该在将其发送到JwtAuthenticator之前解码JWT(从AES)。
现在,我有了一个安全配置。
@Override
protected void configure(HttpSecurity http) throws Exception {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new KeycloakRoleConverter());
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/users/status/check")
.hasRole("developer")
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.decoder(new JWTDecoder())
.jwtAuthenticationConverter(jwtAuthenticationConverter);
}
和一个JWT解码器
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtException;
import java.text.ParseException;
public class JWTDecoder implements JwtDecoder {
@Override
public Jwt decode(String token) throws JwtException {
//decrypt from AES here
JWT jwt = null;
try {
jwt = JWTParser.parse(token);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
函数应该返回org.springframework.security.oauth2.jwt.Jwt
,如何将String token
转换为Jwt?
我尝试了以下操作,但出现了问题。
private Jwt createJwt(String token, JWT parsedJwt) {
try {
Map<String, Object> headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject());
Map<String, Object> claims = parsedJwt.getJWTClaimsSet().getClaims();
return Jwt.withTokenValue(token)
.headers(h -> h.putAll(headers))
.claims(c -> c.putAll(claims))
.build();
} catch (Exception ex) {
if (ex.getCause() instanceof ParseException) {
throw new JwtException("There is a problem parsing the JWT.");
} else {
throw new JwtException("There is a problem decoding the JWT.");
}
}
}
我收到的错误:
异常错误:时间戳的类型必须为“即时:java.lang.Long
我使用Keycloak来生成JWT。因此,www.example.com中标记的exp字段jwt.io是"exp": 1657363340,
。但是在我的代码中解析JWT后,它更改为Date格式。因此,我将exp更改为Instant
,最后的方法如下所示:
private Jwt createJwt(String token, JWT parsedJwt) {
try {
Map<String, Object> headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject());
Map<String, Object> claims = parsedJwt.getJWTClaimsSet().getClaims();
Jwt.Builder finalJwt = Jwt.withTokenValue(token)
.headers(h -> h.putAll(headers))
.claims(c -> c.putAll(claims));
finalJwt.expiresAt(((Date) claims.get("exp")).toInstant());
return finalJwt.build();
} catch (Exception ex) {
if (ex.getCause() instanceof ParseException) {
throw new JwtException("There is a problem parsing the JWT: " + ex.getMessage());
} else {
throw new JwtException("There is a problem decoding the JWT: " + ex.getMessage());
}
}
}
但问题仍然存在。
2条答案
按热度按时间6bc51xsx1#
这可能是由于令牌的到期日期是一个时间戳,而它应该是一个数字(长整数)。或者您正在尝试将时间戳解析为长整数。
5fjcxozz2#
正如@Jose告诉我的,我用
Instant
类型的时间戳设置过期时间的值。然后,我将它设置为JWT的exp
和iat
字段。我的最终函数如下所示: