首页 > 解决方案 > Spring Boot Oauth2 资源服务器 UserDetailsS​​ervice

问题描述

试图让 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
         }
     }
     @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());
            }
         }

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

标签: spring-bootspring-securityspring-security-oauth2spring-oauth2userdetailsservice

解决方案


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

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);
      }

    }
@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);

        }

这终于做了我需要的


推荐阅读