Spring Security で保護された Stormpath Spring アプリケーションを作成したい開発者がライブラリとして使用する Spring Security 構成を作成しています。
そのためにWebSecurityConfigurerAdapter
、Stormpath Access Controls とconfigure(HttpSecurity)
を使用して StormpathAuthenticationProvider
をサブクラス化し、定義しましたconfigure(AuthenticationManagerBuilder)
。これはすべて、この抽象クラスとその具象サブクラスで確認できます。
@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);
}
}
要するに、基本的にログインとログアウトのメカニズムを定義し、CSRF コードを統合して Spring Security のコードとうまく連携させます。
この時点まで、すべて正常に動作します。
しかし、これは単なる「ライブラリ」であり、ユーザーにはその上に独自のアプリケーションを構築してもらいたいと考えています。
そのため、ユーザーがライブラリをどのように使用するかを示すサンプル アプリケーションを作成しました。
基本的に、ユーザーは独自のWebSecurityConfigurerAdapter
. このような:
@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();
}
}
これが実際に必要な場合は、WebApplicationInitializer
次のようになります。
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, "/*");
}
}
このコードはすべて正しく起動します。に行くとlocalhost:8080
、ようこそ画面が表示されます。に行くとlocalhost:8080/login
、ログイン画面が表示されます。しかし、localhost:8080/restricted
次の行があるため、ログイン ページにリダイレクトされるはずですhttp.authorizeRequests().antMatchers("/restricted").fullyAuthenticated();
。ただし、Access Denied
代わりにページが表示されます。
次に、アプリのアクセス制御にログイン URL を追加すると、次のようになります。
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().loginPage("/login")
.and()
.authorizeRequests().antMatchers("/restricted").fullyAuthenticated();
}
ログインページにリダイレクトされますが、資格情報を送信するとすぐに、すべての構成が実際にはこのフィルターチェーンの一部ではないことを意味する CSRF 問題が発生します。
すべてをデバッグすると、それぞれWebApplicationInitializer
が独自のフィルター チェーンを持つ独自のインスタンスを持っているようです。私はそれらが何らかの形で連結されることを期待していますが、実際には起こっていないようです...
誰もこのようなことを試したことがありますか?
public class SpringSecurityWebAppConfig extends StormpathWebSecurityConfiguration
ところで: の代わりにユーザーが実行できる回避策としてSpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter
。このように機能しますが、ユーザーには純粋なSpring Securityコードを持たせStormpathWebSecurityConfiguration
、その目標から逸脱して拡張したいと考えています。
すべてのコードはここで見ることができます。Spring 用の Stormpath Spring Security ライブラリは にありextensions/spring/stormpath-spring-security-webmvc
ます。ライブラリを使用した Sample App は の下にありexamples/spring-security-webmvc
ます。
実行するのは非常に簡単です...ここで説明されているように、Stormpath に登録するだけです。次に、spring_security_extension_redirect_to_login_not_working
ブランチをチェックアウトして、次のようにサンプル アプリを起動できます。
$ git clone git@github.com: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
次に、に移動しlocalhost:8080/restricted
て、ログイン ページにリダイレクトされていないことを確認できます。
どんな助けでも大歓迎です!