【发布时间】:2020-06-02 04:04:37
【问题描述】:
我想自定义spring security提供的OAuth授权服务器的一些代码。负责生成 /oauth/authorize 的代码是一个名为 AuthorizationEndpoint 的 bean。在 AuthorizationServerEndpointsConfiguration 类中,以下代码创建了 AuthorizationEndpoint 类的 bean:
@Bean
public AuthorizationEndpoint authorizationEndpoint() throws Exception {
AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint();
FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator());
authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
authorizationEndpoint.setTokenGranter(tokenGranter());
authorizationEndpoint.setClientDetailsService(clientDetailsService);
authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices());
authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
authorizationEndpoint.setUserApprovalHandler(userApprovalHandler());
return authorizationEndpoint;
}
我想用一个新的自定义 bean 覆盖它。我创建了一个扩展 AuthorizationEndpoint 的类。现在我已经在这个新类中粘贴了相同的代码。
public class AuthorizationEndpointCustom extends AuthorizationEndpoint {
创建 bean:
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
AuthorizationServerEndpointsConfiguration asec;
@Bean
// @Order(value = Ordered.LOWEST_PRECEDENCE)
@Primary
public AuthorizationEndpoint authorizationEndpoint () {
AuthorizationEndpointCustom authorizationEndpoint = new AuthorizationEndpointCustom();
FrameworkEndpointHandlerMapping mapping = asec.getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
authorizationEndpoint.setProviderExceptionHandler(asec.getEndpointsConfigurer().getExceptionTranslator());
authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
authorizationEndpoint.setTokenGranter(asec.getEndpointsConfigurer().getTokenGranter());
authorizationEndpoint.setClientDetailsService(clientDetailsService);
authorizationEndpoint.setAuthorizationCodeServices(asec.getEndpointsConfigurer().getAuthorizationCodeServices());
authorizationEndpoint.setOAuth2RequestFactory(asec.getEndpointsConfigurer().getOAuth2RequestFactory());
authorizationEndpoint.setOAuth2RequestValidator(asec.getEndpointsConfigurer().getOAuth2RequestValidator());
authorizationEndpoint.setUserApprovalHandler(asec.getEndpointsConfigurer().getUserApprovalHandler());
return authorizationEndpoint;
}
private String extractPath(FrameworkEndpointHandlerMapping mapping, String page) {
String path = mapping.getPath(page);
if (path.contains(":")) {
return path;
}
return "forward:" + path;
}
当我尝试创建这个新类的 bean 时,遇到以下错误:
应用程序启动失败
说明:
bean 'authorizationEndpoint',定义在 org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration, 无法注册。具有该名称的 bean 已经 在类路径资源中定义 [com/example/demo/AuthorizationServerConfig.class] 和覆盖是 已禁用。
行动:
考虑重命名其中一个 bean 或通过设置启用覆盖 spring.main.allow-bean-definition-overriding=true
通过将建议的配置添加到 application.properties,错误就会消失。但是新的 bean 并没有取代框架 bean。在我的代码的另一部分中,我从 applicationContext 访问了 AuthorizationEndpoint。我调用了这个对象的 .getClass() ,它是框架中的同一个 bean:
“org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint”
如何强制 spring 使用我的 bean?
【问题讨论】:
-
我不确定
.getClass()是否是最好的测试方法。之前的错误表明您正在更换 bean。无论如何,您可以排除 Autoconfiguration 类,您可以在其中找到带有@SpringBootApplication(exclude=<Configurationclass>.class)的 spring 代码,但这意味着您必须自己实现整个配置类。 -
嗨@PeMa。谢谢你的建议。这当然是一种考虑的方式。但我发现有一种简单的方法可以覆盖框架端点。
-
关于 bean 被覆盖的问题,我认为实际上我自己的 bean 被框架 bean 覆盖了。反之亦然
标签: spring oauth-2.0 authorization