Spring Sprin OAuth2中TokenEndpoint的定制
我想在Spring框架中提供TokenEndpoint类的自定义实现 我复制了spring的TokenEndpoint类,并对所需的位置进行了更改。但是当应用程序启动时,我总是得到错误Spring Sprin OAuth2中TokenEndpoint的定制,spring,spring-security,spring-security-oauth2,spring-oauth2,Spring,Spring Security,Spring Security Oauth2,Spring Oauth2,我想在Spring框架中提供TokenEndpoint类的自定义实现 我复制了spring的TokenEndpoint类,并对所需的位置进行了更改。但是当应用程序启动时,我总是得到错误 Caused by: java.lang.IllegalStateException: TokenGranter must be provided 我已经在OAuthConfig中提供了TokenGranter的实现,但spring并没有考虑到这一点 @Override public void configur
Caused by: java.lang.IllegalStateException: TokenGranter must be provided
我已经在OAuthConfig中提供了TokenGranter的实现,但spring并没有考虑到这一点
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.pathMapping("/oauth/token", "/oauth/token/v1")
.tokenServices(tokenServices())
.tokenGranter(tokenGranter())
.authenticationManager(authenticationManager).tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer()).accessTokenConverter(accessTokenConverter());
}
@Bean
@Primary
public TokenGranter tokenGranter() {
TokenGranter tokenGranter = null;
if (tokenGranter == null) {
tokenGranter = new TokenGranter() {
private CompositeTokenGranter delegate;
@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
if (delegate == null) {
delegate = new CompositeTokenGranter(getDefaultTokenGranters());
}
return delegate.grant(grantType, tokenRequest);
}
};
}
return tokenGranter;
}
我甚至尝试在我的定制TokenEndpoint类中提供这个实现。
目前,定制TokenEndpoint的实现与Spring的TokenEndpoint完全相同
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
private List<TokenGranter> getDefaultTokenGranters() {
ClientDetailsService clientDetails = clientDetailsService();
AuthorizationServerTokenServices tokenServices = tokenServices();
AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices();
OAuth2RequestFactory requestFactory = requestFactory();
List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails,
requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory));
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
tokenGranters.add(implicit);
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory));
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetails,
requestFactory));
}
return tokenGranters;
}
private DefaultTokenServices createDefaultTokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(true);
tokenServices.setClientDetailsService(clientDetailsService());
tokenServices.setTokenEnhancer(tokenEnhancer());
addUserDetailsService(tokenServices, new CustomDetailsService());
return tokenServices;
}
private ClientDetailsService clientDetailsService() {
ClientDetailsService clientDetailsService = null;
clientDetailsService = new InMemoryClientDetailsService();
addUserDetailsService(createDefaultTokenServices(), new CustomDetailsService());
return clientDetailsService;
}
private void addUserDetailsService(DefaultTokenServices tokenServices, UserDetailsService userDetailsService) {
if (userDetailsService != null) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(
userDetailsService));
tokenServices
.setAuthenticationManager(new ProviderManager(Arrays.<AuthenticationProvider> asList(provider)));
}
}
private AuthorizationCodeServices authorizationCodeServices() {
AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices();
return authorizationCodeServices;
}
private OAuth2RequestFactory requestFactory() {
OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService());
return requestFactory;
}
@Bean
public JwtTokenStore tokenStore() {
JwtTokenStore jwtTokenStore = new JwtTokenStore(accessTokenConverter());
return jwtTokenStore;
}
@Bean
@Primary
public AuthorizationServerTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter() {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
return accessToken;
}
};
return converter;
}
OAuth2AccessToken token=getTokenGranter().grant(tokenRequest.getGrantType(),tokenRequest);
私有列表getDefaultTokenGranters(){
ClientDetailsService clientDetails=ClientDetailsService();
AuthorizationServerTokenServices tokenServices=tokenServices();
AuthorizationCodeServices AuthorizationCodeServices=AuthorizationCodeServices();
OAuth2RequestFactory requestFactory=requestFactory();
List tokenGranters=new ArrayList();
添加(新授权代码TokenGranter)(tokenServices、authorizationCodeServices、clientDetails、,
),;
添加(新的RefreshTokenGranter(tokenServices、clientDetails、requestFactory));
ImplicitTokenGranter implicit=新ImplicitTokenGranter(令牌服务、clientDetails、requestFactory);
tokenGranters.add(隐式);
添加(新的ClientCredentialsTokenGranter(tokenServices、clientDetails、requestFactory));
如果(authenticationManager!=null){
添加(新资源所有者PasswordTokenGranter(authenticationManager、tokenServices、clientDetails、,
),;
}
返回授权人;
}
私有DefaultTokenServices createDefaultTokenServices(){
DefaultTokenServices tokenServices=新的DefaultTokenServices();
setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setreUserFreshToken(true);
setClientDetailsService(clientDetailsService());
setTokenEnhancer(tokenEnhancer());
addUserDetailsService(令牌服务,新的CustomDetailsService());
退货服务;
}
私有客户端详细信息服务客户端详细信息服务(){
ClientDetailsService ClientDetailsService=null;
clientDetailsService=新的InMemoryClientDetailsService();
addUserDetailsService(createDefaultTokenServices(),新的CustomDetailsService());
返回客户端详细信息服务;
}
私有void addUserDetailsService(DefaultTokenServices令牌服务,UserDetailsService UserDetailsService){
if(userDetailsService!=null){
PreAuthenticateAuthenticationProvider=新的PreAuthenticateAuthenticationProvider();
setPreAuthenticatedUserDetailsService(新的UserDetailsByNameServiceWrapper(
用户详细信息服务);
代币服务
.setAuthenticationManager(新的ProviderManager(Arrays.asList(provider));
}
}
私有授权CodeServices授权CodeServices(){
AuthorizationCodeServices AuthorizationCodeServices=新的InMemoryAuthorizationCodeServices();
返回授权代码服务;
}
私有OAuth2RequestFactory requestFactory(){
OAuth2RequestFactory requestFactory=新的默认OAuth2RequestFactory(clientDetailsService());
退货申请工厂;
}
@豆子
公共JwtTokenStore tokenStore(){
JwtTokenStore JwtTokenStore=新的JwtTokenStore(accessTokenConverter());
返回jwtTokenStore;
}
@豆子
@初级的
公共授权服务器令牌服务令牌服务(){
final DefaultTokenServices DefaultTokenServices=新的DefaultTokenServices();
defaultTokenServices.setAccessTokenValiditySeconds(-1);
setTokenStore(tokenStore());
返回服务;
}
@豆子
公共令牌增强器令牌增强器(){
返回新的CustomTokenEnhancer();
}
@豆子
公共JwtAccessTokenConverter accessTokenConverter(){
最终JwtAccessTokenConverter=新JwtAccessTokenConverter(){
@凌驾
公共OAuth2AccessToken增强(OAuth2AccessToken accessToken,OAuth2Authentication身份验证){
返回accessToken;
}
};
回流转换器;
}
我已经想了好几天了,但是运气不好。因此,任何帮助都将不胜感激。为什么您需要再次实现
TokenEndpoint
您可以创建TokenGranter
bean并将其注入默认端点
哪里是getDefaultTokenGranters()
方法
看起来您的authorizationServerEndpointsConfiger
源代码的副本不完整
更新:
如果要自定义令牌响应,请使用TokenEnhancer
例如:
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
OurUser user = (OurUser) authentication.getPrincipal();
final Map<String, Object> additionalInfo = new HashMap<>();
Map<String, Object> userDetails = new HashMap<>();
userDetails.put(USERID, user.getId().getId());
userDetails.put(NAME, user.getName());
userDetails.put(MOBILE, user.getMobile());
userDetails.put(EMAIL, user.getEmail());
additionalInfo.put(USERINFO, userDetails);
// Set additional information in token for retriving in #org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
我知道这个问题已经很老了,但我遇到了同样的问题,没有找到一个关于定制令牌端点的完整指南。我无法使用TokenEnhancer,因为我需要更改响应的标题。所以,这是一个适合我的版本 您可以像往常一样定义覆盖控制器:
@RequestMapping(value = "/oauth/token")
public class CustomTokenEndpoint extends TokenEndpoint {
@PostMapping
public ResponseEntity<OAuth2AccessToken> postAccessToken(
Principal principal,
@RequestParam Map<String, String> parameters
) throws HttpRequestMethodNotSupportedException {
ResponseEntity<OAuth2AccessToken> defaultResponse = super.postAccessToken(principal, parameters);
// do some work
return defaultResponse;
}
}
这是踢球的人。您需要允许在应用程序中覆盖Springbean。属性
:
spring.main.allow-bean-definition-overriding: true
希望这对某人有所帮助我的目标是定制使用访问令牌返回响应的方式。因此,我正在实现令牌端点。我为AuthorizationServerEndpointsConfiguration中所有必需的方法提供了实现。没有贴在这里,因为方法太多了。我的最终目标是调整从端点返回响应的方式,而不是提供新的TokenGranter。您应该使用TokenEnhancer。我复制了spring的TokenEndpoint类,并对所需位置进行了更改。这是否意味着您有两个
标记端点
@Bean
@Primary
public TokenEndpoint tokenEndpoint(AuthorizationServerEndpointsConfiguration conf) {
TokenEndpoint tokenEndpoint = new CustomTokenEndpoint();
tokenEndpoint.setClientDetailsService(conf.getEndpointsConfigurer().getClientDetailsService());
tokenEndpoint.setProviderExceptionHandler(conf.getEndpointsConfigurer().getExceptionTranslator());
tokenEndpoint.setTokenGranter(conf.getEndpointsConfigurer().getTokenGranter());
tokenEndpoint.setOAuth2RequestFactory(conf.getEndpointsConfigurer().getOAuth2RequestFactory());
tokenEndpoint.setOAuth2RequestValidator(conf.getEndpointsConfigurer().getOAuth2RequestValidator());
tokenEndpoint.setAllowedRequestMethods(conf.getEndpointsConfigurer().getAllowedTokenEndpointRequestMethods());
return tokenEndpoint;
}
spring.main.allow-bean-definition-overriding: true