无法在单个 Oauth 安全 Spring 控制器中拥有安全和非安全端点

Unable to have a secure and non secure endpoint in a single Oauth secured Spring controller

我正在使用 Spring 启动将 REST api 组合在一起,它将通过 OAuth2 进行保护。我构建了一个安全应用程序,它可以很好地管理 jwt 令牌。

我正在组装一个单独的应用程序,它将处理一些一般的用户配置文件资源请求,例如忘记密码、注册和配置文件获取操作。这是用 EnableOAuth2Resource 注释的,它正确地将 OAuth2AuthenticationProcessingFilter 添加到过滤器链。

@SpringBootApplication
@EnableOAuth2Resource
public class ProfileApplication extends SpringBootServletInitializer {

    public static void main(String[] args) throws IOException {
        SpringApplication.run(ProfileApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(ProfileApplication.class);
    }
}

我面临的挑战是我无法找到一种方法来配置安全性,以便 POST 对 /profiles 端点的请求是不安全的,而对 GET 或 PUT 的请求则通过提供的派生 @AuthenticationPrincipal 传递不记名令牌。

我想在 API 中包含以下内容 POST /profile 创建一个新用户 - 不安全 GET /profile/{id} 通过 id 获取用户 - 需要管理员权限或用户已授权 POST /password/reset - 开始密码重置 - 不安全

我有以下 bean 来配置安全性

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(-10) //SecurityProperties.ACCESS_OVERRIDE_ORDER)
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/public/**").permitAll()                
                .antMatchers(HttpMethod.POST, "/profiles/**").permitAll()
                .antMatchers(HttpMethod.GET, "/profiles/**").fullyAuthenticated()
                .antMatchers("/password/**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and()
                .csrf().disable();
    }
}

使用上面的 GET 端点调用失败并出现 403 错误,没有任何尝试从令牌中查找当前用户,但是 post 将通过。查看日志,我不再在过滤器链中看到 OAuth2AuthenticationProcessingFilter。我尝试添加一些额外的过滤器似乎导致它不再被注册。

这个控制器方法看起来像:

@RequestMapping(method = {RequestMethod.GET}, value="/profiles/{login:.+}")
@ResponseBody
public ResponseEntity<Profile> get(@AuthenticationPrincipal Principal currentUser, @PathVariable String login) {

如果我将订单设置为 SecurityProperties.ACCESS_OVERRIDE_ORDER,那么 GET 请求会起作用,并且我会根据 jwt 承载令牌中的配置文件看到针对我的 oauth 服务的查找,但是 POST 请求要么配置文件或密码控制器失败并显示 401。因此,代码似乎永远不会到达此过滤器,而是被 OAuth2AuthenticationProcessingFilter 拦截,并且请求立即失败。

有没有办法在使用@EnableOAuth2Resource 时部分保护 Spring 启动应用程序?我是否必须设置不同的配置 bean 来提供必要的覆盖,如果需要,基于什么接口?

我认为您应该将 oauth2 资源从 SecurityConfig 中的请求匹配器中移走,并允许它们由资源服务器过滤器处理 - class 正在扩展 ResourceServerConfigurerAdapter.

我的回答受到 Dave Syer 给出的回答的启发 . You can find a good security config here

或者尝试给 bean 一个更高的顺序。

@maleenc 上面的建议是正确的。我缺少以下 ResourceServerConfigurerAdapter。添加我的 OAuth2ServerConfiguration class 并删除其他安全过滤器解决了我的问题

@Configuration
public class OAuth2ServerConfiguration {
    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/", "/public/**").permitAll()                
                    .antMatchers("/password/**").permitAll()
                    .antMatchers(HttpMethod.POST, "/profiles").permitAll()
                    .and()
                    .csrf().disable();
        }
    }
}