2014-10-30 17 views
9

Tôi đang cố gắng để thiết lập vai trò thứ bậc trong ứng dụng Boot mùa xuân của tôi không thành công. Tôi đã làm tất cả những gì đã được nói ở những nơi khác nhau trên Internet. Nhưng với không ai trong số họ có tôi đã có thể giải quyết vấn đề.Xuân Boot + Xuân An + Cấu trúc Vai trò

Đây là mã của lớp SecurityConfig tôi. Khi tôi đăng nhập vào ứng dụng với một người dùng có ROLE_ADMIN, nó sẽ có thể truy xuất dữ liệu từ '/ users', nhưng hiện tại tôi nhận được một Access Denied Exception. Nếu người dùng có thông tin xác thực ROLE_USER, nó hoạt động tốt. Bất cứ ai có thể giúp tôi tìm ra những gì không thành công? Cảm ơn trước.

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

Cập nhật: Đây là mã cập nhật với đề nghị của bạn, nhưng vẫn không hoạt động.

Trả lời

3

Bạn cần phải thiết lập hệ thống phân cấp vai trò trên cử tri biểu web. Một cái gì đó như:

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

Cập nhật: Bạn cũng có thể thử thiết lập xử lý biểu thức trên như thế này:

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

Nó không hoạt động theo cách đó. Tôi vẫn nhận được cùng một ngoại lệ bị từ chối truy cập – Mario

+0

@Mario Hãy thử cập nhật của tôi. – holmis83

+0

Tôi đã làm điều đó ngày hôm qua rồi ... Tôi không biết tại sao không làm việc vì tôi đã làm mọi thứ có thể mà không thành công. – Mario

3

Bạn phải thiết lập hệ thống phân cấp vai trò trên 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; 
    } 
} 

Kiểm tra Javadoc for @EnableGlobalMethodSecurity để biết thêm thông tin. Đặc biệt chú ý: rằng EnableGlobalMethodSecurity vẫn phải được đưa vào các lớp mở rộng GlobalMethodSecurityConfiguration để xác định các thiết lập.

7

Tôi chỉ cần đi qua các thiết lập để chắc chắn sẽ giúp bạn có được chạy ngay bây giờ. Đây là thỏa thuận:

Bạn đã đưa chú thích này @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) nhưng không hiển thị bất kỳ mã nào để sử dụng Pre/Post Authorize/Filter vì vậy tôi không biết nếu bạn thực sự cần nó.

  1. Nếu bạn không cần phải có trình độ lớp/phương pháp an ninh/lọc sau đó tất cả các bạn cần làm là:

    @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()) 

Bạn don' t phải ghi đè bằng accessDecisionManager của riêng bạn nếu tất cả những gì bạn cần là giới thiệu một hệ thống phân cấp vai trò.

  1. Nếu bạn cũng cần bảo mật cấp lớp/phương pháp, tức làsử dụng PreAuthorize, PostAuthorize, PreFilter, PostFilter về phương pháp/lớp học của bạn sau đó cũng tạo ra một @Configuration như thế này trong classpath của bạn (và loại bỏ các chú thích @EnableGlobalMethodSecurity từ lớp GlobalMethodSecurityConfig của bạn):

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

    }

tôi sẽ cung cấp cho các đặt tên GlobalMethodSecurityConfig cho lớp mới này và thay đổi lớp GlobalMethodSecurityConfig hiện tại của bạn thành WebSecurityConfig hoặc một cái gì đó để phản ánh rằng đó là thiết lập bảo mật cho tầng web.

Tôi xác định RoleHierarchy bean trong webSecurityConfig và tiêm/sử dụng nó trong globalMethodSecurityConfig, nhưng bạn có thể làm điều đó theo bất kỳ cách nào bạn muốn, miễn là bạn không tạo 2 bean không cần thiết.

Hy vọng điều này sẽ hữu ích.

+0

Xin chào, cảm ơn câu trả lời của bạn! Thật không may, Spring không cho phép tôi loại bỏ chú thích '@ EnableGlobalMethodSecurity' khỏi lớp' WebSecurityConfig' của mình - tôi nhận được 'IllegalArgumentException: Một ServletContext được yêu cầu để cấu hình xử lý servlet mặc định'. Bất kỳ trợ giúp nào đánh giá cao – kiedysktos

+0

OK, tôi đã tìm thấy giải pháp. Có vẻ như lời khuyên của bạn ở điểm 2. không tốt cho tôi vì nó hoạt động theo cách khác. Xem câu trả lời ở đây: http://stackoverflow.com/questions/43468285/springboot-method-based-hierarchical-roles-security-servletcontext-is-require/43473615#43473615 – kiedysktos

0

Để bật bảo mật cấp phương thức (tức là @EnableGlobalMethodSecurity (prePostEnabled = true)) cùng với vai trò phân cấp hỗ trợ trên WebSecurityConfigurerAdapter.

1.Chỉ cần tách riêng Phân cấp vai trò trên bất kỳ lớp nào khác được chú thích bằng @Bean
2.Từ chối bằng cách sử dụng @Autowired on WebSecurityConfigurerAdapter. Nó hoạt động hoàn hảo trên các dự án của tôi.

Vui lòng xem mã của tôi.

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

}

hy vọng nó sẽ giúp bạn.

Các vấn đề liên quan