2015-04-15 10 views
2

У меня возникла проблема с использованием аннотации @PreAuthorize. Даже если мой пользователь не владеет заданными ролями, мои защищенные методы выполняются.Весенняя безопасность - @PreAuthorize не работает

Мой контроллер:

@Controller 
@RequestMapping("/stats/distributions") 
public class DistributionStatsController { 

    @PreAuthorize("hasAnyAuthority('AK_LOCAL_DIST_INT', 'AK_ADMIN')") 
    @RequestMapping(method = RequestMethod.POST, consumes = "application/json; charset=utf-8", 
     produces = "application/json; charset=utf-8") 
    public @ResponseBody List<DistributionStatsResource> filter(@RequestBody DistributionStatsResource resource, 
      @RequestParam(required = false, value = "documentId") Long documentId, 
      @RequestParam(required = false, value = "distStatus") EnumDistributionStatus distributionStatus, 
      Pageable pageable, HttpServletRequest request) { 
    } 
} 

Вот моя конфигурация пружины безопасности:

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    /** Defines the AuthenticationManager/providers. */ 
    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(preAuthenticatedAuthenticationProvider()); 
    } 

    @Override 
    public void configure(WebSecurity web) throws Exception { 
     web.ignoring().antMatchers("/css/**", "/font/**", "/icones/**", "/img/**"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     // TODO Configure HTTP URLs and filters. 
     http.authorizeRequests().antMatchers("/views/access401.html").permitAll().antMatchers("/views/admin/agent.html").hasAuthority("AK_ADMIN") 
     .antMatchers("/views/admin/agentDetail.html").hasAuthority("AK_ADMIN").antMatchers("/views/admin/businesses.html") 
     .hasAuthority("AK_ADMIN").antMatchers("/views/admin/distributors.html").hasAuthority("AK_ADMIN") 
     .antMatchers("/views/admin/distributionReportList.html").hasAuthority("AK_ADMIN") 
     .antMatchers("/views/documentEdition/documentDetail.html").hasAnyAuthority("AK_CENTRAL_DIST", "AK_LOCAL_DIST_INT", "AK_ADMIN") 

     .antMatchers("/views/home/home.html").fullyAuthenticated().antMatchers("/views/distribution/distribution.html") 
     .hasAnyAuthority("AK_LOCAL_DIST_INT", "AK_ADMIN").antMatchers("/views/distribution/distributionEdit.html") 
     .hasAnyAuthority("AK_LOCAL_DIST_INT", "AK_ADMIN").antMatchers("/views/admin/types.html").hasAuthority("AK_ADMIN").and() 
      .exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint()).and().addFilter(habileFilter()).csrf().disable(); // Disable CSRF 
     // protection. 
    } 

    /** Gives an alias to the authenticationManager. */ 
    @Override 
    @Bean(name = "authenticationManager") 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 

    /** A unauthorized entry point. */ 
    @Bean 
    public AuthenticationEntryPoint unauthorizedEntryPoint() { 
     return new ForbiddenEntryPoint(); 
    } 

    /** The user details service used by the PreAuthenticatedAuthenticationProvider. */ 
    @Bean 
    public AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> myAuthenticationUserDetailsService() { 
     return new NgwisAuthenticationUserDetailsService(); 
    } 

    /** The PreAuthenticatedAuthenticationProvider. */ 
    @Bean 
    public PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() { 
     PreAuthenticatedAuthenticationProvider pro = new PreAuthenticatedAuthenticationProvider(); 
     pro.setPreAuthenticatedUserDetailsService(myAuthenticationUserDetailsService()); 
     return pro; 
    } 

    // ---- Filters. 

    /** Builds an Habile filter. 
    * 
    * @return the habile filter. */ 
    @Bean 
    public RequestHeaderAuthenticationFilter habileFilter() throws Exception { 
     NgwisRequestHeaderAuthenticationFilter filter = new NgwisRequestHeaderAuthenticationFilter(); 
     filter.setPrincipalRequestHeader("SM_USER"); 
     filter.setCredentialsRequestHeader(NgwisRequestHeaderAuthenticationFilter.HABILE_FILTER_NAME); 
     filter.setAuthenticationManager(authenticationManager()); 
     return filter; 
    } 
} 

(Этот класс упоминается в моем классе базовой конфигурации)

Мой RequestHeaderAuthenticationFilter класс:

public class NgwisRequestHeaderAuthenticationFilter extends RequestHeaderAuthenticationFilter { 

    public static final String HABILE_FILTER_NAME = "HABILE"; 

    /** Pour mise à disposition des informations de sécurité */ 
    public static final String BEAN_SECURITIES = "com.airfrance.springsecurity.securities"; 

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(NgwisRequestHeaderAuthenticationFilter.class); 

    // AK de l'utilisateur en fonction de ses profils 
    private UserAccessKeys userAccessKeys = null; 

    // Pour passer l'info au niveau de la config de spring security 
    private String credentialsRequestHeader; 

    @Inject 
    private IAgentService agentService; 

    @Inject 
    private DozerBeanMapper mapper; 

    /** Credentials aren't usually applicable, but if a {@code credentialsRequestHeader} is set, this will be read and used as 
    * the credentials value. Otherwise a dummy value will be used. */ 
    @Override 
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { 
     Collection<GrantedAuthority> tmp = new ArrayList<GrantedAuthority>(); 
     User user = new User(request.getRemoteUser().toUpperCase(), "none", false, false, false, false, tmp); 
     if (credentialsRequestHeader != null) { 
      if (credentialsRequestHeader.equalsIgnoreCase("HABILE")) { 
       try { 
        LdapBean ldBean = LdapBeanAccessor.getLdapBean(request); 
        if (ldBean != null) { 
         userAccessKeys = new UserAccessKeys(request, ldBean, agentService, mapper); 
         request.getSession().setAttribute(BEAN_SECURITIES, userAccessKeys); 
         List<String> auths = new ArrayList<String>(); 
         for (GrantedAuthority auth : userAccessKeys.getAuthorities()) { 
          auths.add(auth.getAuthority()); 
         } 
         logger.debug("User {} connected with authorities {}", userAccessKeys.getLogin(), StringUtils.join(auths, ", ")); 
         user = new User(request.getRemoteUser().toUpperCase(), "none", true, true, true, true, userAccessKeys.getAuthorities()); 
        } 
       } catch (NoLdapBeanInSessionException e) { 
        logger.error("Erreur lors de la connexion de {}", request.getRemoteUser().toUpperCase(), e); 
       } catch (NotProtectedGetLdapException e) { 
        logger.error("Erreur technique ", e); 
       } 
       if (userAccessKeys.getAgent() != null) { 
        return user; 
       } else { 
        return null; 
       } 
      } else { 
       return request.getHeader(credentialsRequestHeader); 
      } 
     } 

     return "N/A"; 
    } 

    @Override 
    public void setCredentialsRequestHeader(String credentialsRequestHeader) { 
     Assert.hasText(credentialsRequestHeader, "credentialsRequestHeader must not be empty or null"); 
     this.credentialsRequestHeader = credentialsRequestHeader; 
    } 
} 

Я проверил в этом классе, мы получим полномочия зарегистрированного пользователя. Кажется, все в порядке.

Когда я запускаю этот код с пользователем только с ролью AK_CONSULT, метод выполняется и не запускается 503 ERROR.

Спасибо за помощь.

+0

При использовании XML для настройки Spring, параметр «pre-post» должен быть включен в контексте Spring MVC, а не в Spring Security. Может ли это быть той же проблемой, с которой вы столкнулись (я не большой поклонник использования аннотаций для настройки Spring)? – sp00m

+0

Вы можете посмотреть здесь, я думаю, что это тоже проблема и может помочь: http://stackoverflow.com/questions/29275890/can-not-get-the-secured-method-security-annotations-working-in -spring-security/29277396 # 29277396 –

+0

Похоже на мою проблему. Но для его решения он установил аннотацию на уровне сервиса, а не на контроллерах (что бы мне хотелось). И, как говорится в комментарии, в Интернете есть много примеров, где эта аннотация находится в контроллерах. – Truche

ответ

3

Мои коллеги нашли трюк. Аннотирование @EnableGlobalMethodSecurity (prePostEnabled = true) не должно быть в классе конфигурации spring-security, но в классе конфигурации сервлета.

@Configuration 
@EnableWebMvc 
@EnableSpringDataWebSupport 
@EnableJpaRepositories 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@ComponentScan(basePackages = { "mypackage.spring.rest" }, excludeFilters = @Filter(type = FilterType.ANNOTATION, value = Configuration.class)) 
public class SpringRestConfiguration { 

} 

И это работает!

Смежные вопросы