Sha*_*.es 4 java spring oauth-2.0 jwt nimbus-jose-jwt
我正在使用 Spring boot 资源服务器。身份验证服务器发出 JWT。该 JWT 使用密钥重新编码(使用 AES),并且在资源服务器中,我应该在将 JWT 发送到 JwtAuthenticator 之前对其进行解码(从 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);
}
Run Code Online (Sandbox Code Playgroud)
和 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;
}
}
Run Code Online (Sandbox Code Playgroud)
那我该怎么办?该函数应该返回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.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到的错误:
java.lang.IllegalArgumentException:时间戳必须是 Instant 类型:java.lang.Long
"exp": 1657363340,。但是在我的代码中解析 JWT 后,它更改为日期格式。所以,我将 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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
但问题仍然存在。
Instant正如@Jose 告诉我的,我使用时间戳类型设置了过期时间的值。然后,我将其设置为JWT 的exp和字段。iat我的最终功能如下:
Map<String, Object> headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject());
Map<String, Object> claims = new HashMap<>();
for (String key : parsedJwt.getJWTClaimsSet().getClaims().keySet()) {
Object value = parsedJwt.getJWTClaimsSet().getClaims().get(key);
if (key.equals("exp") || key.equals("iat")) {
value = ((Date) value).toInstant();
}
claims.put(key, value);
}
return Jwt.withTokenValue(token)
.headers(h -> h.putAll(headers))
.claims(c -> c.putAll(claims))
.build();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8865 次 |
| 最近记录: |