java - 如何使用经典身份验证将 spring-security-oauth 服务器添加到现有 Web 应用程序?

标签 java spring spring-security-oauth2

我有一个具有基于经典 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/

相关文章:

java LinkedList 与自己的实现

java - 如何更正 Spring MVC RequestMapping 顺序?

spring - org.hibernate.exception.GenericJDBCException : Cannot open connection

spring-boot - Spring cloud Feign OAuth2 请求拦截器不工作

spring - Grails Spring Security OAuth2提供者对具有正确承载 token 的资源的请求重定向到登录

java - 无法在 spring 中处理配置类的导入候选

java - 如何在java中使用键盘使 Sprite 移动(libgdx)

java - setApplicationDestinationPrefixes 的用途是什么?

Spring MVC RequestMapping 匹配错误的 URL

java - SpringFramework 和 Hibernate 应用程序 HTTP 状态 404 Java