我有一个具有基于经典 cookie 身份验证的 Web 应用程序。这就是它的配置方式:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint());
http.authorizeRequests()
.antMatchers("/some/restricted/urls*").access("hasRole('admin')")
.antMatchers("/some/public/urls").permitAll()
.antMatchers("/**").access("hasRole('registered')");
}
@Autowired
protected void configureAuthenticationManager(final AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userService)
.passwordEncoder(passwordEncoder);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
现在我想允许外部应用程序使用 OAuth2 访问我的一些用户数据。首先,我添加了这样的身份验证:
@Configuration
@EnableAuthorizationServer
public class OAuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private AuthenticationManager auth;
@Bean
public JdbcTokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
@Bean
public JdbcClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final ApprovalStoreUserApprovalHandler approvalHandler = new ApprovalStoreUserApprovalHandler();
approvalHandler.setClientDetailsService(clientDetailsService());
endpoints
.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(auth)
.tokenStore(tokenStore())
.userApprovalHandler(approvalHandler)
.pathMapping("/oauth/confirm_access", "/api/oauth2/confirm_access")
.pathMapping("/oauth/token", "/api/oauth2/token")
.pathMapping("/oauth/check_token", "/api/oauth2/check_token")
.pathMapping("/oauth/token_key", "/api/oauth2/token_key")
.pathMapping("/oauth/authorize", "/api/oauth2/authorize");
}
}
一切似乎都工作得很好。我的网络应用程序总体上似乎可以正常工作,我可以获取代码并将其交换为访问 token 。仅访问 token 本身是相当无用的,因此我想添加一个需要有效访问 token 的服务。为此,我添加了以下内容:
@Configuration
@EnableResourceServer
public class Oauth2ResourcesConfigurationAdapter extends ResourceServerConfigurerAdapter {
@Autowired
private AuthenticationManager auth;
@Autowired
private OAuthServerConfig oAuthServerConfig;
@Override
public void configure(final ResourceServerSecurityConfigurer resources) throws Exception {
resources
.authenticationManager(auth)
.tokenStore(oAuthServerConfig.tokenStore());
}
}
但是这给了我一个异常(exception):
Caused by: java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer@6dd1c3ed to already built object
at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.add(AbstractConfiguredSecurityBuilder.java:192)
我阅读了调试的源代码并尽我所能地谷歌,但我只是无法弄清楚这里发生了什么。我发现的最接近的提示是 this ticket on GitHub ,但是它没有对问题进行解释,并且我按照票证中的建议编写自己的配置非常不成功,可能是因为我不知道问题是什么,因此我需要更改什么。
最佳答案
与此同时,robsilvia 在上面列出的 github 票证中给出了答案。简而言之,它表示必须将此方法添加到 Oauth2ResourcesConfigurationAdapter
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
但是,这导致我的 oauth 配置干扰了我的经典 Web 应用程序安全配置,该配置不再正常工作。不过我确实发现了"multiple HttpSecurity"因此我最终通过使用这种变体解决了这个问题:
@Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/path/to/oauth/endpoints/*"),
new AntPathRequestMatcher("/oauth/protected/resource")
))
.authorizeRequests().anyRequest().authenticated();
}
关于java - 如何使用经典身份验证将 spring-security-oauth 服务器添加到现有 Web 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33618307/