2014-10-30 2 views
9

Я пытаюсь настроить иерархические роли в моем приложении Spring Boot без успеха. Я сделал все, что было сказано в разных местах в Интернете. Но ни один из них не смог решить проблему.Spring Boot + Spring Security + Иерархические роли

Вот код моего класса SecurityConfig. Когда я вхожу в приложение с пользователем с ROLE_ADMIN, он должен иметь возможность извлекать данные из «/ users», но в настоящее время я получаю исключение, связанное с доступом. Если у пользователя есть учетные данные ROLE_USER, он работает нормально. Может ли кто-нибудь помочь мне понять, что не удается? Спасибо заранее.

@Configuration 
@EnableWebMvcSecurity 
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private SigpaUserDetailsService userDetailsService; 

    @Bean 
    public RoleHierarchyImpl roleHierarchy() { 
     RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
     roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); 
     return roleHierarchy; 
    } 

    @Bean 
    public RoleHierarchyVoter roleVoter() {  
     return new RoleHierarchyVoter(roleHierarchy()); 
    } 

    @Bean 
    public DefaultWebSecurityExpressionHandler expressionHandler(){ 
     DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler(); 
     expressionHandler.setRoleHierarchy(roleHierarchy()); 
     return expressionHandler; 
    } 

    @Bean 
    @SuppressWarnings(value = { "rawtypes" }) 
    public AffirmativeBased accessDecisionManager() {  
     List<AccessDecisionVoter> decisionVoters = new ArrayList<AccessDecisionVoter>(); 
     WebExpressionVoter webExpressionVoter = new WebExpressionVoter(); 
     webExpressionVoter.setExpressionHandler(expressionHandler()); 
     decisionVoters.add(webExpressionVoter); 
     decisionVoters.add(roleVoter()); 
     return new AffirmativeBased(decisionVoters); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
      .accessDecisionManager(accessDecisionManager()) 
      .expressionHandler(expressionHandler()) 
      .antMatchers("https://stackoverflow.com/users/**") 
       .access("hasRole('ROLE_USER')") 
      .anyRequest().authenticated(); 
     http 
      .formLogin() 
       .loginPage("/login").permitAll() 
       .and() 
      .logout() 
       .permitAll(); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder registry) 
      throws Exception { 
     registry.userDetailsService(userDetailsService); 
    } 
} 

Update: Вот код обновляется с вашим предложением, но по-прежнему не работает.

ответ

3

Вам необходимо установить иерархию роли в элементе избирателя веб-выражения. Что-то вроде:

DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler(); 
expressionHandler.setRoleHierarchy(roleHierarchy); 
webExpressionVoter.setExpressionHandler(expressionHandler); 

Update: Можно также попробовать установив выше обработчик выражения, как это:

http 
    .authorizeRequests() 
    .expressionHandler(expressionHandler) 
    ... 
+0

Это не работает. Я по-прежнему получаю то же исключение с правами доступа – Mario

+0

@Mario Попробуйте мое обновление. – holmis83

+0

Я сделал это уже вчера ... Я понятия не имею, почему это не работает, потому что я сделал все возможное без каких-либо успехов. – Mario

3

Вы должны установить иерархию ролей на MethodSecurityExpressionHandler:

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public static class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration { 
    @Autowired 
    private RoleHierarchy roleHierarchy; 

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
     final DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); 
     handler.setRoleHierarchy(this.roleHierarchy); 
     return handler; 
    } 
} 

Для получения дополнительной информации отметьте Javadoc for @EnableGlobalMethodSecurity. Особенно обратите внимание: , что EnableGlobalMethodSecurity по-прежнему должны быть включены в класс, расширяющий GlobalMethodSecurityConfiguration, чтобы определить настройки.

7

Я только что прошел через эти настройки, так что, безусловно, вы подниметесь сейчас. Вот сделка:

Вы внесли эту аннотацию @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true), но не указали какой код использовать Pre/Post Authorize/Filter, поэтому я не знаю, действительно ли вам это нужно.

  1. Если вам не нужно, что безопасность/фильтрации на уровне класса/метод, то все, что вам нужно сделать, это:

    @Bean 
    public RoleHierarchyImpl roleHierarchy() { 
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); 
        return roleHierarchy; 
    } 
    

и

 private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { 
      DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); 
      defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy()); 
      return defaultWebSecurityExpressionHandler; 
     } 

http 
     .authorizeRequests() 
     .expressionHandler(webExpressionHandler()) 

Вы надеваете» t нужно переопределить с помощью собственного accessDecisionManager, если вам нужно только ввести иерархию ролей.

  1. Если вам также нужна безопасность уровня класса/метода, т. Е.используя PreAuthorize, PostAuthorize, PreFilter, PostFilter ваших методов/классов, затем также создать @Configuration, как это в вашем пути к классам (и удалить @EnableGlobalMethodSecurity аннотацию из вашего класса GlobalMethodSecurityConfig):

    @Configuration 
    @EnableGlobalMethodSecurity(prePostEnabled=true) 
    public class AnyNameYouLike extends GlobalMethodSecurityConfiguration { 
    
    @Resource 
    private RoleHierarchy roleHierarchy; 
    
    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
        DefaultMethodSecurityExpressionHandler expressionHandler = (DefaultMethodSecurityExpressionHandler) super.createExpressionHandler(); 
        expressionHandler.setRoleHierarchy(roleHierarchy); 
        return expressionHandler; 
    } 
    

    }

Я бы дать имя GlobalMethodSecurityConfig для этого нового класса и измените текущий класс GlobalMethodSecurityConfig на WebSecurityConfig или что-то, чтобы отразить, что это параметр безопасности для веб-уровня.

Я определяю bean-компонент RoleHierarchy в webSecurityConfig и добавляю/использую его в файле globalMethodSecurityConfig, но вы можете сделать это любым способом, если вы не создадите 2 боба без необходимости.

Надеюсь, это поможет.

+0

Привет, спасибо за ваш ответ! К сожалению, Spring не позволяет мне удалить аннотацию '@ EnableGlobalMethodSecurity' из моего класса« WebSecurityConfig »- я получаю' IllegalArgumentException: для настройки обработки сервлетов по умолчанию требуется ServletContext'. Любая помощь оценена – kiedysktos

+0

Хорошо, я нашел решение. Похоже, ваш совет в пункте 2. был не таким хорошим, поскольку для меня это работает наоборот. См. Ответ здесь: http://stackoverflow.com/questions/43468285/springboot-method-based-hierarchical-roles-security-servletcontext-is-require/43473615#43473615 – kiedysktos

0

Чтобы включить защиту уровня метода (например, @EnableGlobalMethodSecurity (prePostEnabled = true)) вместе с поддержкой иерархической роли в WebSecurityConfigurerAdapter.

1.Just нужно отделить RoleHierarchy на любой другой класс с аннотацией @Bean
2.Inject его с помощью @Autowired на WebSecurityConfigurerAdapter. Он безупречно работает над моими проектами.

Пожалуйста, загляните в мой код.

WeSecurityConfig.class

@Configuration 
    @EnableGlobalMethodSecurity(prePostEnabled = true) 
    @EnableWebSecurity 
    public class AppSecurityConfig extends WebSecurityConfigurerAdapter{ 
    @Autowired 
    private RoleHierarchy roleHierarchy; 

    private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() { 
    DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler  = new DefaultWebSecurityExpressionHandler(); 
    defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy); 
    return defaultWebSecurityExpressionHandler; 
} 


@Override 
public void configure(WebSecurity web) throws Exception{ 
    super.configure(web); 
    web.ignoring().antMatchers("/static/**"); 
} 

@Override 
public void configure(HttpSecurity http) throws Exception{ 
    http. 
      authorizeRequests() 
      .expressionHandler(webExpressionHandler()) 
      .antMatchers("/static/**","/bower_components/**","/").permitAll() 
      .antMatchers("/user/login","/user/login?error").anonymous() 
      .anyRequest().authenticated() 
      .and() 
      .formLogin().loginPage("/user/login").passwordParameter("password").usernameParameter("username") 
      .defaultSuccessUrl("/") 
      .permitAll() 
      .and() 
      .logout().logoutUrl("/user/logout") 
      .logoutSuccessUrl("/user/login?logout") 
      .and().csrf(); 

} 


@Override 
public void configure(AuthenticationManagerBuilder auth) throws Exception{ 
    auth.authenticationProvider(daoAuthenticationProvider()); 
} 

public DaoAuthenticationProvider daoAuthenticationProvider(){ 
    final DaoAuthenticationProvider auth = new DaoAuthenticationProvider(); 
    auth.setUserDetailsService(userDetailService); 
    auth.setPasswordEncoder(passwordEncoder); 
    return auth; 
} 

}

BeanConfiguration.class

@Configuration 
public class BeanConfiguration { 

@Bean 
public RoleHierarchy roleHierarchy(){ 
    RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
    /* tricks lies here */ 
    roleHierarchy.setHierarchy("ROLE_SUPREME > ROLE_ADMIN ROLE_ADMIN > ROLE_OPERATOR ROLE_OPERATOR > ROLE_GUEST"); 
    return roleHierarchy; 
} 

}

Надежда Это помогает вам.

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