Spring Boot Oauth2 资源服务器 UserDetailsS​​ervice

MGZ*_*ero 7 spring-security spring-boot spring-security-oauth2 userdetailsservice spring-oauth2

尝试让 UserDetailsS​​ervice 为我设置的 oauth2 资源服务器工作。我能够成功验证 jwt,但我似乎没有做任何事情来让它调用 loadUserByUsername 方法。最初使用 SAML 并且它可以工作,但现在我已经切换到 Oauth2,但我无法让它工作。

     @Service
     public class OauthUsersDetailsServiceImpl implements UserDetailsService{
         @Override
         public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
             //some user loading junk here - this is never called
         }
     }
Run Code Online (Sandbox Code Playgroud)
     @Configuration
        @EnableGlobalMethodSecurity(prePostEnabled = true)
        @EnableWebSecurity
         public class SecurityConfig extends WebSecurityConfigurerAdapter {
            
            @Override
            protected void configure(HttpSecurity http) throws Exception
            {
                //test key for now
                SecretKeySpec key = new SecretKeySpec("private key0000000000000000000000000000000".getBytes(), "HMACSHA256");
                

                http
                    .authorizeRequests()
                    .antMatchers(/*some endpoints im excluding from auth - this all works*/)
                    .permitAll().and()
                    .authorizeRequests()
                    .anyRequest().authenticated().and()
                    .oauth2ResourceServer().jwt().decoder(NimbusJwtDecoder.withSecretKey(key).build());
            }
         }
Run Code Online (Sandbox Code Playgroud)

我通过谷歌发现,我可以将类注册为 @service 的 bean,spring 会直接拾取它,但它不起作用。我还尝试通过 AuthenticationManagerBuilder 添加它,但这也不起作用。我的猜测是,jwt 方面有自己的 UserDetailsS​​ervice,它已实现,并且优先于我的。也就是说,让我的调用的正确方法是什么,或者在身份验证完成后以某种方式手动调用我的用户加载逻辑并覆盖主体对象是否更好?我需要在调用端点之前发生这种情况,以便 PreAuthorize 可以检查 UserDetailsS​​ervice 加载的角色。

MGZ*_*ero 4

弄清楚了。希望这对遇到同样问题的人有所帮助。我必须在链中添加一个自定义过滤器来调用我的用户详细信息服务并覆盖上下文:

public class Oauth2AuthorizationFilter extends GenericFilterBean {

        @Autowired
        private OauthUsersDetailsServiceImpl oauthUsersDetailsServiceImpl;
      
      public Oauth2AuthorizationFilter (OauthUsersDetailsServiceImpl userDetailsService) {
        this.oauthUsersDetailsServiceImpl = userDetailsService;
      }
      
      
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {

        SecurityContext context = SecurityContextHolder.getContext();
        if(context.getAuthentication() != null && !(context.getAuthentication().getPrincipal() instanceof Users)) {
          
          UserDetails user = oauthUsersDetailsServiceImpl.loadUserByUsername(((Jwt)context.getAuthentication().getPrincipal()).getClaimAsString("user_name")); 
          UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
          context.setAuthentication(authentication);
        }
        
        chain.doFilter(request, response);
      }

    }
Run Code Online (Sandbox Code Playgroud)
@Override
        protected void configure(HttpSecurity http) throws Exception
        {
            //test key for now
            SecretKeySpec key = new SecretKeySpec("private key0000000000000000000000000000000".getBytes(), "HMACSHA256");
            
            http.authorizeRequests().antMatchers(/*bunch of junk...*/).permitAll().and().authorizeRequests().anyRequest().authenticated().and()
                .oauth2ResourceServer().jwt().decoder(NimbusJwtDecoder.withSecretKey(key).build());
            
            http.addFilterAfter(jwtAuthTokenFilterBean(), SwitchUserFilter.class);

        }
Run Code Online (Sandbox Code Playgroud)

这终于满足了我的需要