2015-10-06 11 views
5

Tôi đang tạo cấu hình Spring Security để sử dụng làm thư viện của bất kỳ nhà phát triển nào muốn tạo ứng dụng Springpath Spring được bảo mật bằng Spring Security.Nhiều WebSecurityConfigurerAdapter: một như một thư viện, trong những người dùng khác có thể thêm quyền truy cập bảo mật của riêng mình

Đối với điều đó tôi đã phân loại phụ WebSecurityConfigurerAdapter và xác định các điều khiển truy cập Stormpath trong configure(HttpSecurity) cũng như Stormpath AuthenticationProvider bằng phương tiện configure(AuthenticationManagerBuilder). Tất cả điều này có thể được nhìn thấy trong lớp trừu tượng này và bê tông sub-class của nó:

@Order(99) 
public abstract class AbstractStormpathWebSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    //Removed properties and beans for the sake of keeping focus on the important stuff 

    /** 
    * The pre-defined Stormpath access control settings are defined here. 
    * 
    * @param http the {@link HttpSecurity} to be modified 
    * @throws Exception if an error occurs 
    */ 
    protected void configure(HttpSecurity http, AuthenticationSuccessHandler successHandler, LogoutHandler logoutHandler) 
      throws Exception { 

     if (loginEnabled) { 
      http 
        .formLogin() 
        .loginPage(loginUri) 
        .defaultSuccessUrl(loginNextUri) 
        .successHandler(successHandler) 
        .usernameParameter("login") 
        .passwordParameter("password"); 
     } 

     if (logoutEnabled) { 
      http 
        .logout() 
        .invalidateHttpSession(true) 
        .logoutUrl(logoutUri) 
        .logoutSuccessUrl(logoutNextUri) 
        .addLogoutHandler(logoutHandler); 

     } 

     if (!csrfProtectionEnabled) { 
      http.csrf().disable(); 
     } else { 
      //Let's configure HttpSessionCsrfTokenRepository to play nicely with our Controllers' forms 
      http.csrf().csrfTokenRepository(stormpathCsrfTokenRepository()); 
     } 
    } 

    /** 
    * Method to specify the {@link AuthenticationProvider} that Spring Security will use when processing authentications. 
    * 
    * @param auth the {@link AuthenticationManagerBuilder} to use 
    * @param authenticationProvider the {@link AuthenticationProvider} to whom Spring Security will delegate authentication attempts 
    * @throws Exception if an error occurs 
    */ 
    protected void configure(AuthenticationManagerBuilder auth, AuthenticationProvider authenticationProvider) throws Exception { 
     auth.authenticationProvider(authenticationProvider); 
    } 
} 

@Configuration 
public class StormpathWebSecurityConfiguration extends AbstractStormpathWebSecurityConfiguration { 

    //Removed beans for the sake of keeping focus on the important stuff 

    @Override 
    protected final void configure(HttpSecurity http) throws Exception { 
     configure(http, stormpathAuthenticationSuccessHandler(), stormpathLogoutHandler()); 
    } 

    @Override 
    protected final void configure(AuthenticationManagerBuilder auth) throws Exception { 
     configure(auth, super.stormpathAuthenticationProvider); 
    } 
} 

Nói tóm lại, chúng tôi về cơ bản xác định cơ chế đăng nhập và đăng xuất của chúng tôi và tích hợp mã CSRF của chúng tôi để chơi độc đáo với một mùa xuân an nhân.

Tính đến thời điểm này, mọi thứ đều hoạt động OK.

Nhưng đây chỉ là "thư viện" và chúng tôi muốn người dùng xây dựng ứng dụng của riêng họ trên đầu trang của nó.

Vì vậy, chúng tôi đã tạo một ứng dụng Mẫu để minh họa cách người dùng sẽ sử dụng thư viện của chúng tôi.

Về cơ bản, người dùng sẽ muốn tạo riêng của mình WebSecurityConfigurerAdapter. Như thế này:

@EnableStormpathWebSecurity 
@Configuration 
@ComponentScan 
@PropertySource("classpath:application.properties") 
@Order(1) 
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter { 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests().antMatchers("/restricted").fullyAuthenticated(); 
    } 

} 

Trong trường hợp này là thực sự cần thiết, WebApplicationInitializer trông như thế này:

public class WebAppInitializer implements WebApplicationInitializer { 

    @Override 
    public void onStartup(ServletContext sc) throws ServletException { 

     AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); 
     context.register(SpringSecurityWebAppConfig.class); 
     context.register(StormpathMethodSecurityConfiguration.class); 
     sc.addListener(new ContextLoaderListener(context)); 

     ServletRegistration.Dynamic dispatcher = sc.addServlet("dispatcher", new DispatcherServlet(context)); 
     dispatcher.setLoadOnStartup(1); 
     dispatcher.addMapping("/"); 

     //Stormpath Filter 
     FilterRegistration.Dynamic filter = sc.addFilter("stormpathFilter", new DelegatingFilterProxy()); 
     EnumSet<DispatcherType> types = 
       EnumSet.of(DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST); 
     filter.addMappingForUrlPatterns(types, false, "/*"); 

     //Spring Security Filter 
     FilterRegistration.Dynamic securityFilter = sc.addFilter(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, DelegatingFilterProxy.class); 
     securityFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*"); 
    } 
} 

Tất cả điều này đang khởi động lên một cách chính xác. Nếu tôi truy cập localhost:8080 Tôi thấy màn hình chào mừng. Nếu tôi truy cập localhost:8080/login Tôi thấy màn hình đăng nhập. Nhưng, nếu tôi truy cập vào localhost:8080/restricted, tôi sẽ được chuyển hướng đến trang đăng nhập vì chúng tôi có dòng này: http.authorizeRequests().antMatchers("/restricted").fullyAuthenticated();. Tuy nhiên, tôi thấy trang Access Denied.

Sau đó, nếu tôi thêm các url đăng nhập trong kiểm soát truy cập của ứng dụng, như thế này:

protected void configure(HttpSecurity http) throws Exception { 
    http 
      .formLogin().loginPage("/login") 
      .and() 
      .authorizeRequests().antMatchers("/restricted").fullyAuthenticated(); 
} 

Nó bây giờ chuyển hướng tôi đến trang đăng nhập nhưng ngay sau khi tôi gửi các thông tin tôi nhận được một vấn đề ý nghĩa CSRF rằng tất cả cấu hình của chúng tôi không thực sự là một phần của chuỗi bộ lọc này.

Khi tôi gỡ lỗi tất cả, dường như mỗi WebApplicationInitializer đều có cá thể riêng với Chuỗi bộ lọc riêng. Tôi hy vọng họ sẽ được nối nhau bằng cách nào đó nhưng có vẻ như nó không thực sự xảy ra ...

Bất cứ ai đã từng thử một cái gì đó như thế này?

BTW: Là người dùng giải pháp có thể làm public class SpringSecurityWebAppConfig extends StormpathWebSecurityConfiguration thay vì SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter. Bằng cách này, nó hoạt động nhưng tôi muốn người dùng có mã Spring Security thuần túy và mở rộng từ phân đoạn StormpathWebSecurityConfiguration của chúng tôi từ mục tiêu đó.

Tất cả mã có thể được xem here. Thư viện an ninh Springpath Spring cho mùa xuân dưới extensions/spring/stormpath-spring-security-webmvc. Ứng dụng mẫu sử dụng thư viện dưới examples/spring-security-webmvc.

Nó rất đơn giản để chạy ... Bạn chỉ cần đăng ký Stormpath as explained here.Sau đó, bạn có thể kiểm tra các chi nhánh spring_security_extension_redirect_to_login_not_working và bắt đầu ứng dụng mẫu như thế này:

$ git clone git[email protected]:mrioan/stormpath-sdk-java.git 
$ git checkout spring_security_extension_redirect_to_login_not_working 
$ mvn install -DskipTests=true 
$ cd examples/spring-security-webmvc 
$ mvn jetty:run 

Sau đó, bạn có thể đi đến localhost:8080/restricted để thấy rằng bạn đang không được chuyển hướng đến trang đăng nhập.

Bất kỳ trợ giúp nào được đánh giá rất nhiều!

Trả lời

3

Theo kinh nghiệm của tôi, có vấn đề với việc có nhiều sự cố khi cấu hình bảo mật khi khởi động WebSecurityConfigurer.

Cách tốt nhất để giải quyết vấn đề này là đặt cấu hình thư viện của bạn thành SecurityConfigurerAdapters có thể được áp dụng khi thích hợp.

public class StormpathHttpSecurityConfigurer 
     extends AbstractStormpathWebSecurityConfiguration 
     implements SecurityConfigurer<DefaultSecurityFilterChain, HttpSecurity> { 

    //Removed beans for the sake of keeping focus on the important stuff 

    @Override 
    protected final void configure(HttpSecurity http) throws Exception { 
     configure(http, stormpathAuthenticationSuccessHandler(), stormpathLogoutHandler()); 
    } 
} 

public class StormpathAuthenticationManagerConfigurer 
     extends AbstractStormpathWebSecurityConfiguration 
     implements SecurityConfigurer<AuthenticationManager, AuthenticationManagerBuilder> { 

    //Removed beans for the sake of keeping focus on the important stuff 

    @Override 
    protected final void configure(AuthenticationManagerBuilder auth) throws Exception { 
     configure(auth, super.stormpathAuthenticationProvider); 
    } 
} 

Sau đó bạn có người dùng của bạn apply này trong cấu hình riêng của họ:

@EnableStormpathWebSecurity 
@Configuration 
@ComponentScan 
@PropertySource("classpath:application.properties") 
@Order(1) 
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
       .antMatchers("/restricted").fullyAuthenticated() 
       .and() 
      .apply(new StormPathHttpSecurityConfigurer(...)) 
     ; 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.apply(new StormPathAuthenticationManagerConfigurer(...)); 
    } 
} 
+2

Đó thực sự là cách chúng tôi cuối cùng thực hiện điều đó. Để làm sạch hơn, chúng tôi đã nhập cấu hình tĩnh. Mọi thứ cuối cùng trông như sau: https://github.com/stormpath/stormpath-sdk-java/blob/master/examples/spring-security-spring-boot-webmvc-bare-bones/src/main/java/com/ stormpath/spring/boot/examples/SpringSecurityWebAppConfig.java – mario

+0

Tệp được liên kết đã thay đổi. Mục mới: https://github.com/stormpath/stormpath-sdk-java/blob/master/examples/spring-security-webmvc/src/main/java/com/stormpath/spring/examples/SpringSecurityWebAppConfig.java – mario

-2

Đó chắc chắn là vấn đề liên quan đến một trong hai đơn đặt hàng của Người chống đối hoặc đã không chỉ định LẦN người dùng mà bạn cho phép truy cập URL.

Bạn có điều gì ở trên "/ bị hạn chế"?

Có điều gì đó chặn hoàn toàn mọi thứ bên dưới URL đó không? Trước tiên, bạn nên chỉ định các URL cụ thể hơn, các URL tổng quát.

Hãy thử định cấu hình URL ở trên đúng cách (hoặc cho tôi biết tôi có thể giúp gì cho bạn), có thể áp dụng "fullyAuthenticated" cũng "allowAll" ROLE trên URL mẹ "/ restricted".

+0

Nó không chỉ là một vấn đề đặt hàng. Nếu tôi làm điều này: @ Override protected void configure (HttpSecurity http) throws Exception { http .authorizeRequests() antMatchers ("/ **") permitAll() .và() .authorizeRequests().. .antMatchers ("/ restricted"). hoàn toànĐược xác thực(); } Sau đó, tôi được chuyển hướng nhưng tôi tình cờ gặp một vấn đề CSRF (đã làm việc propelry trong cấu hình trong 'AbstractStormpathWebSecurityConfiguration'). Có vẻ như có 2 bộ lọc chuỗi độc lập đang chơi ở đây mà không được ghép nối đúng cách. – mario

+0

Về bản chất, bạn có một chuỗi các bộ lọc bảo mật, theo thứ tự. Nếu bạn đang gặp phải sự cố CSRF, thì người dùng của bạn chưa được xác thực chính xác trước khi nhấn URL đó. Nếu không, nếu URL không yêu cầu bất kỳ phương thức xác thực nào, chỉ cần tắt CSRF bằng .csrf(). –

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