Как обновить аутентификацию в auditorAware - PullRequest
1 голос
/ 01 августа 2020
    @Configuration
    @EnableJpaAuditing(auditorAwareRef = "auditorProvider")
    public class JpaAuditingConfiguration {
    
      @Bean
      @Scope(value= ConfigurableBeanFactory.SCOPE_PROTOTYPE)
      public AuditorAware<String> auditorProvider() {

        Authentication authentication 
             = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return () -> Optional.<String>empty();
        }
        return () -> Optional.of(authentication.getName());
      }
    
      public static void main(String[] args) {
        SpringApplication.run(JpaAuditingConfiguration.class, args);
      }
    }
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      private UserDetailServiceImpl userDetailsService;

      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) 
                               throws Exception {
        auth.userDetailsService(userDetailsService)
             .passwordEncoder(new BCryptPasswordEncoder());
      }

      @Override
      protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().cors().and()
                .logout()
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .logoutSuccessUrl("/logout/success")
                .and().authorizeRequests()
                .antMatchers(HttpMethod.POST, "/login").permitAll()
                .antMatchers(HttpMethod.GET, "/logout/**").permitAll()
                .anyRequest().authenticated().and()
                // Filter for the api/login requests
                .addFilterBefore(new LoginFilter("/login", 
                                     authenticationManager()),
                        UsernamePasswordAuthenticationFilter.class)
                // Filter for other requests to check JWT in header
                .addFilterBefore(new AuthenticationFilter(), 
                    UsernamePasswordAuthenticationFilter.class);
        
    }
    public class AuthenticationFilter extends GenericFilterBean {
      @Override
      public void doFilter(ServletRequest request, 
                           ServletResponse response, 
                           FilterChain filterChain) 
                           throws IOException, ServletException {
       Authentication authentication 
        = AuthenticationService
                  .getAuthentication((HttpServletRequest)request);
    
       SecurityContext securityContext 
                    = SecurityContextHolder.getContext();
       securityContext.setAuthentication(authentication);
       filterChain.doFilter(request, response);
      }
    }

auditorProvider кажется, вызывается только один раз при запуске приложения. authentication вызывается до того, как он будет установлен в doFilter. authentication объект всегда имеет значение null и не обновляется, если он установлен позже в doFilter. Когда я обновляю строку в db, createdBy и lastModifiedBy всегда равны нулю.

My doFilter кажется, вызывается при обработке HTTP-запроса.

Я следовал руководству чтобы узнать о безопасности Spring, но после устранения неполадок в течение нескольких часов и выполнения многих аналогичных руководств по-прежнему не могу понять, как правильно установить аутентификацию в последовательности, поэтому, когда я обновляю строку, spring обновит lastModifiedBy и createdBy автоматически.

1 Ответ

1 голос
/ 01 августа 2020
  • Ваша проблема в том, что вы создаете анонимный AuditorAware, но вы оцениваете SecurityContextHolder.getContext().getAuthentication() вне тела, поэтому все, что в это время создания, будет храниться внутри тела.
    @Bean
    @Scope(value= ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public AuditorAware<String> auditorProvider() {

        return () -> {
            Authentication authentication 
                    = SecurityContextHolder.getContext().getAuthentication();
            return Optional.ofNullable(authentication)
                    .map(Authentication::getName);
        };
    }
  • Можно сказать, что у вас есть SCOPE_PROTOTYPE, но это бесполезно, если оно было автоматически подключено к одноэлементному экземпляру, используемому фреймворком.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...