在spring boot中,配置Resource server后,如果访问令牌为JWT且发行者为客户端提供获取公共RSA密钥的端点,则可以选择设置security.oauth2.resource.jwk.key-set-uri
属性。以JWK格式验证。
从此JWK启动密钥库的预期行为是什么?该属性正在加载ResourceServerProperties.JWK
,但后来是什么。 spring boot应该调用这个URI并获取jwks然后创建一个商店供我验证吗?
我正在按照本教程设置密钥库http://www.baeldung.com/spring-security-oauth-jwt
的配置 @Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
但我没有加载.pem
公钥,而是想从jwk
加载它。
答案 0 :(得分:2)
如果要使用JWKS,请使用JwkTokenStore
代替JwtTokenStore
。
spring-security-oauth2/jwk在内部根据auth0 spec
进行密钥加载和管理您还可以看到有关自动配置的文档,但是我觉得配置起来非常简单(请参阅下文)。
我们不必进行任何验证,因为JwkTokenStore使用@Value("{jsecurity.oauth2.resource.jwk.key-set-uri}")
公开的JWKS通过JwkDefinitionSource JwkVerifyingJwtAccessTokenConverter设置了验证。
但是,Spring的spring-security-oauth2/jwk类没有任何公共构造函数,我们经常需要并且可以在AccessTokenConversion中执行任何自定义步骤,就像通常需要将jwt内容提取到auth上下文中一样,我们可以始终向JwkTokenStore
注入自定义转换器import org.springframework.security.oauth2.provider.token.store.jwk.*;
import org.springframework.security.oauth2.provider.token.store.*
import org.springframework.security.oauth2.provider.token.*;
import java.utl.*;
@Configuration
class JwtConfiguration {
@Bean
public DefaultTokenServices tokenServices(final TokenStore tokenStore) {
final DefaultTokenServices dts = new DefaultTokenServices();
dts.setTokenStore(tokenStore);
dts.setSupportRefreshToken(true);
return dts;
}
@Bean
public TokenStore tokenStore(
@Value("{jsecurity.oauth2.resource.jwk.key-set-uri}") final String jwksUrl,
final JwtAccessTokenConverter jwtAccessTokenConverter) {
return new JwkTokenStore(jwksUrl, jwtAccessTokenConverter, null);
}
@Bean
public JwtAccessTokenConverter createJwtAccessTokenConverter() {
final JwtAccessTokenConverter converter;
converter.setAccessTokenConverter(new DefaultAccessTokenConverter() {
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
final OAuth2Authentication auth = super.extractAuthentication(map);
auth.setDetails(map); //this will get spring to copy JWT content into
return auth;
}
}
return conveter;
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableResourceServer
class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private String resourceId;
private TokenStore tokenStore;
public ResourceServerConfig(
@Value("\${jwt.reourceId}") private String resourceId,
private TokenStore tokenStore) {
this.resourceId = resourceId;
this.tokenStore = tokenStore;
}
/**
* Ensures request to all endpoints ore a
@Override
public void configure(final HttpSecurity http) {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/**").authenticated();
}
/**
* Configure resources
* Spring OAuth expects "aud" claim in JWT token. That claim's value should match to the resourceId value
* (if not specified it defaults to "oauth2-resource").
*/
@Override
public void configure(final ResourceServerSecurityConfigurer resources) {
resources.resourceId(resourceId).tokenStore(tokenStore);
}
}
答案 1 :(得分:0)
此实现的主要目标是使用相应的JWK(JSON WEB TOKEN KEY SET)在本地验证JWT。用于验证的JWK使用JWT的kid header参数和JWK的kid属性进行匹配。
服务器可以在本地验证此令牌,而无需发出任何网络请求,与数据库通信等。这可能会使会话管理更快,因为您无需在每次请求时从数据库(或缓存)加载用户,只需要运行一小部分本地代码。这可能是人们喜欢使用JWT的最大原因:它们是无国籍的。