在Java Spring中从IdentityServer4中提取JWK,可以通过以下步骤实现:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
application.properties
或application.yml
文件进行配置。spring:
security:
oauth2:
client:
provider:
identityserver:
issuer-uri: <IdentityServer4的URL>
registration:
identityserver:
client-id: <客户端ID>
client-secret: <客户端密钥>
JwkSetEndpointFilter
类,用于从IdentityServer4的JWK Set端点获取JWK。import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
import org.springframework.security.oauth2.core.OAuth2TokenType;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders;
import org.springframework.security.oauth2.jwt.JwtValidators;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.AuthenticationFilter;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class JwkSetEndpointFilter extends OncePerRequestFilter {
private static final String DEFAULT_JWK_SET_ENDPOINT = "/.well-known/jwks.json";
private static final String DEFAULT_JWK_SET_URI = "/.well-known/openid-configuration";
private final RestTemplate restTemplate;
private final String jwkSetEndpoint;
private final JwtDecoder jwtDecoder;
public JwkSetEndpointFilter() {
this.restTemplate = new RestTemplate();
this.jwkSetEndpoint = DEFAULT_JWK_SET_ENDPOINT;
this.jwtDecoder = createJwtDecoder(DEFAULT_JWK_SET_URI);
}
public JwkSetEndpointFilter(String jwkSetEndpoint, String jwkSetUri) {
Assert.hasText(jwkSetEndpoint, "jwkSetEndpoint must not be empty");
Assert.hasText(jwkSetUri, "jwkSetUri must not be empty");
this.restTemplate = new RestTemplate();
this.jwkSetEndpoint = jwkSetEndpoint;
this.jwtDecoder = createJwtDecoder(jwkSetUri);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String requestUri = request.getRequestURI();
if (requestUri.endsWith(jwkSetEndpoint)) {
ResponseEntity<Map> responseEntity = restTemplate.exchange(RequestEntity.get(URI.create(jwkSetEndpoint)).build(), Map.class);
Map<String, Object> jwkSet = responseEntity.getBody();
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.getWriter().write(jwkSet.toString());
} else {
filterChain.doFilter(request, response);
}
}
private JwtDecoder createJwtDecoder(String jwkSetUri) {
ResponseEntity<Map> responseEntity = restTemplate.exchange(RequestEntity.get(URI.create(jwkSetUri)).build(), Map.class);
Map<String, Object> jwkSetUriResponse = responseEntity.getBody();
List<Map<String, Object>> keys = (List<Map<String, Object>>) jwkSetUriResponse.get("keys");
NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(jwkSetUri);
jwtDecoder.setJwtValidator(createJwtValidator(keys));
return jwtDecoder;
}
private OAuth2TokenValidator<Jwt> createJwtValidator(List<Map<String, Object>> keys) {
List<OAuth2TokenValidator<Jwt>> validators = Collections.singletonList(JwtValidators.createDefault());
return new DelegatingOAuth2TokenValidator<>(validators);
}
}
JwkSetEndpointFilter
添加到过滤器链中。import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig {
@Bean
public FilterRegistrationBean<JwkSetEndpointFilter> jwkSetEndpointFilter() {
FilterRegistrationBean<JwkSetEndpointFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new JwkSetEndpointFilter());
registrationBean.addUrlPatterns("/.well-known/jwks.json");
return registrationBean;
}
}
JwtDecoder
来解码和验证JWT。以下是一个示例:import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private final JwtDecoder jwtDecoder;
@Autowired
public MyController(JwtDecoder jwtDecoder) {
this.jwtDecoder = jwtDecoder;
}
@GetMapping("/decode")
public Jwt decodeJwt(String token) {
return jwtDecoder.decode(token);
}
}
以上就是在Java Spring中从IdentityServer4中提取JWK的步骤。这样你就可以使用Java Spring来处理和验证来自IdentityServer4的JWT了。
请注意,以上示例仅供参考,具体实现可能会根据你的项目需求和IdentityServer4的配置而有所不同。