我想问一下,我的安全配置是否可以在多个罐子中传播。例如,我的项目(myproj.war)定义了@Configuration中的所有安全规则,但我还将其余的@Configuration放在一个单独的jar(rest.jar)中,这样人们就可以将它放在类路径中并立即拥有/ rest / *支持。 这一切都很好,直到我想为其余配置添加安全性。我在我的rest.jar中添加@Configuration和@EnableWebSecurity,但它没有被拾取!我的DigestAuthenticationFilter中有一个断点,它永远不会通过它!但是我可以看到在启动过程中创建了bean,过滤器本身永远不会被触发!
修改 这是我的战争安全网络配置:
@Order(value = 0)
public class StorefrontWebConfig implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
webCtx.register(StorefrontSecurityConfig.class);
webCtx.register(StorefrontMVCConfig.class);
servletContext.addListener(new RequestContextListener());
servletContext.addListener(new HttpSessionMutexListener());
servletContext.addListener(new ContextLoaderListener(webCtx));
servletContext.addListener(new BroadcasterCreator());
/* JAWR */
.... jawr definitions ....
/* Spring Delegating Dispatcher Servlet */
final Servlet dispatcherServlet = new DispatcherServlet(webCtx);
final ServletRegistration.Dynamic dispatcherServletReg = servletContext.addServlet("dispatcherServlet", dispatcherServlet);
dispatcherServletReg.setLoadOnStartup(1);
dispatcherServletReg.setInitParameter("contextConfigLocation", "");
dispatcherServletReg.addMapping("/");
/* Character Encoding Filter */
final FilterRegistration charEncodingfilterReg = servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class);
charEncodingfilterReg.setInitParameter("encoding", "UTF-8");
charEncodingfilterReg.setInitParameter("forceEncoding", "true");
charEncodingfilterReg.addMappingForServletNames(null, false, dispatcherServletReg.getName());
/* Resources Filter */
final FilterRegistration resourcesFilterReg = servletContext.addFilter("resourceFilter", ResourceFilter.class);
resourcesFilterReg.addMappingForUrlPatterns(null, false, "/resources/*");
resourcesFilterReg.addMappingForUrlPatterns(null, false, "/webjars/*");
/* Storefront Delegating Filter */
final FilterRegistration storefrontFilterChainReg = servletContext.addFilter("storefrontFilterChain", DelegatingFilterProxy.class);
storefrontFilterChainReg.addMappingForServletNames(null, false, dispatcherServletReg.getName());
/* HiddenHttpMethodFilter Filter */
final FilterRegistration hiddenHttpMethodFilterReg = servletContext.addFilter("hiddenHttpMethodFilter", HiddenHttpMethodFilter.class);
hiddenHttpMethodFilterReg.addMappingForServletNames(null, false, dispatcherServletReg.getName());
/* Spring Security Delegating Filter */
final FilterRegistration springSecurityFilterChainReg = servletContext.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class);
springSecurityFilterChainReg.addMappingForServletNames(EnumSet.<DispatcherType>of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC), false, dispatcherServletReg.getName());
}
}
还有安全配置:
@Configuration
@EnableWebSecurity
public class StorefrontSecurityConfig {
@Autowired
private ObjectPostProcessor<Object> opp;
@Resource
public ApplicationContext context;
// @formatter:off
@Order(1)
@Configuration
public static class CheckoutStorefrontSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
public ApplicationContext context;
@Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.antMatcher("/checkout/**")
.anonymous().principal("anonymous").authorities("ROLE_ANONYMOUS").and()
.sessionManagement().sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()).and()
.authorizeRequests().and()
.requiresChannel()
.antMatchers("/checkout*").requiresSecure()
.antMatchers("/checkout/**").requiresSecure()
.antMatchers("/checkout/j_spring_security_check").requiresSecure().and()
.formLogin()
.loginProcessingUrl("/checkout/j_spring_security_check").permitAll()
.loginPage("/checkout/login")
.failureHandler(defaultCheckoutAuthenticationFailureHandler())
.successHandler(defaultLoginCheckoutGUIDAuthenticationSuccessHandler()).and()
.logout()
.logoutUrl("/j_spring_security_logout")
.logoutSuccessHandler((SimpleUrlLogoutSuccessHandler) context.getBean(StoreFrontLogoutSuccessHandler.NAME)).and()
.rememberMe().rememberMeServices(context.getBean(DefaultRememberMeServices.class)).and()
.portMapper()
.http(80).mapsTo(443)
.http(8111).mapsTo(8112)
.http(8080).mapsTo(8443).and()
.exceptionHandling().accessDeniedHandler(defaultCheckoutAccessDeniedHandler()).and()
.requestCache().requestCache(httpSessionRequestCache());
}
@Bean(name = {"defaultLoginCheckoutGUIDAuthenticationSuccessHandler", "loginCheckoutGUIDAuthenticationSuccessHandler"})
protected AuthenticationSuccessHandler defaultLoginCheckoutGUIDAuthenticationSuccessHandler() {
final GUIDAuthenticationSuccessHandler guidAuthenticationSuccessHandler = new GUIDAuthenticationSuccessHandler();
guidAuthenticationSuccessHandler.setAuthenticationSuccessHandler(defaultLoginCheckoutAuthenticationSuccessHandler());
return guidAuthenticationSuccessHandler;
}
@Bean(name = {"defaultLoginCheckoutAuthenticationSuccessHandler", "loginCheckoutAuthenticationSuccessHandler"})
protected AuthenticationSuccessHandler defaultLoginCheckoutAuthenticationSuccessHandler() {
final StoreFrontAuthenticationSuccessHandler storeFrontAuthenticationSuccessHandler = new StoreFrontAuthenticationSuccessHandler();
storeFrontAuthenticationSuccessHandler.setDefaultTargetUrl("/checkout");
final Map<UiExperienceLevel, Boolean> forceDefaultTargetForUiExperienceLevel = new HashMap<UiExperienceLevel, Boolean>();
forceDefaultTargetForUiExperienceLevel.put(UiExperienceLevel.MOBILE, Boolean.TRUE);
forceDefaultTargetForUiExperienceLevel.put(UiExperienceLevel.NORMAL, Boolean.TRUE);
storeFrontAuthenticationSuccessHandler.setForceDefaultTargetForUiExperienceLevel(forceDefaultTargetForUiExperienceLevel);
return storeFrontAuthenticationSuccessHandler;
}
@Bean(name = {"defaultCheckoutAuthenticationFailureHandler", "checkoutAuthenticationFailureHandler"})
protected AuthenticationFailureHandler defaultCheckoutAuthenticationFailureHandler() {
final LoginAuthenticationFailureHandler loginAuthenticationFailureHandler = new LoginAuthenticationFailureHandler();
loginAuthenticationFailureHandler.setDefaultFailureUrl("/checkout/login?failed=auth");
return loginAuthenticationFailureHandler;
}
@Bean(name = {"defaultCheckoutAccessDeniedHandler", "checkoutAccessDeniedHandler"})
protected AccessDeniedHandler defaultCheckoutAccessDeniedHandler() {
final AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
accessDeniedHandler.setErrorPage("/403");
return accessDeniedHandler;
}
}
@Order(2)
@Configuration
public static class DefaultStorefrontSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
public ApplicationContext context;
@Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.anonymous().principal("anonymous").authorities("ROLE_ANONYMOUS").and()
.sessionManagement().sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()).and()
.authorizeRequests()
.antMatchers("/my-account*").hasRole("CUSTOMERGROUP")
.antMatchers("/my-account/**").hasRole("CUSTOMERGROUP").and()
.requiresChannel()
.antMatchers("/login").requiresSecure()
.antMatchers("/login/**").requiresSecure()
.antMatchers("/register/**").requiresSecure()
.antMatchers("/signin/**").requiresSecure()
.antMatchers("/j_spring_security_check").requiresSecure()
.antMatchers("/logout").requiresSecure()
.antMatchers("/**").requiresInsecure().and()
.formLogin()
.loginProcessingUrl("/j_spring_security_check").permitAll()
.loginPage("/login").permitAll()
.defaultSuccessUrl("/my-account", false)
.failureHandler(defaultAuthenticationFailureHandler())
.successHandler(defaultLoginGUIDAuthenticationSuccessHandler()).and()
.logout()
.logoutUrl("/j_spring_security_logout")
.logoutSuccessHandler(context.getBean(StoreFrontLogoutSuccessHandler.class)).and() .rememberMe().rememberMeServices(context.getBean(DefaultRememberMeServices.class)).and()
.portMapper()
.http(80).mapsTo(443)
.http(8111).mapsTo(8112)
.http(8080).mapsTo(8443).and()
.exceptionHandling().accessDeniedHandler(defaultAccessDeniedHandler()).and()
.requestCache().requestCache(httpSessionRequestCache());
}
@Bean(name = {"defaultLoginGUIDAuthenticationSuccessHandler", "loginGUIDAuthenticationSuccessHandler"})
protected AuthenticationSuccessHandler defaultLoginGUIDAuthenticationSuccessHandler() {
final GUIDAuthenticationSuccessHandler guidAuthenticationSuccessHandler = new GUIDAuthenticationSuccessHandler();
guidAuthenticationSuccessHandler.setAuthenticationSuccessHandler(defaultLoginAuthenticationSuccessHandler());
return guidAuthenticationSuccessHandler;
}
@Bean(name = {"defaultLoginAuthenticationSuccessHandler", "loginAuthenticationSuccessHandler"})
protected StoreFrontAuthenticationSuccessHandler defaultLoginAuthenticationSuccessHandler() {
final StoreFrontAuthenticationSuccessHandler storeFrontAuthenticationSuccessHandler = new StoreFrontAuthenticationSuccessHandler();
storeFrontAuthenticationSuccessHandler.setDefaultTargetUrl("/my-account");
storeFrontAuthenticationSuccessHandler.setUseReferer(true);
storeFrontAuthenticationSuccessHandler.setRequestCache(httpSessionRequestCache());
final Map<UiExperienceLevel, Boolean> forceDefaultTargetForUiExperienceLevel = new HashMap<UiExperienceLevel, Boolean>();
forceDefaultTargetForUiExperienceLevel.put(UiExperienceLevel.MOBILE, Boolean.TRUE);
forceDefaultTargetForUiExperienceLevel.put(UiExperienceLevel.NORMAL, Boolean.FALSE);
storeFrontAuthenticationSuccessHandler.setForceDefaultTargetForUiExperienceLevel(forceDefaultTargetForUiExperienceLevel);
return storeFrontAuthenticationSuccessHandler;
}
@Bean(name = {"defaultAuthenticationFailureHandler", "authenticationFailureHandler"})
protected AuthenticationFailureHandler defaultAuthenticationFailureHandler() {
final LoginAuthenticationFailureHandler loginAuthenticationFailureHandler = new LoginAuthenticationFailureHandler();
loginAuthenticationFailureHandler.setDefaultFailureUrl("/login?failed=auth");
return loginAuthenticationFailureHandler;
}
@Bean(name = {"defaultAccessDeniedHandler", "accessDeniedHandler"})
protected AccessDeniedHandler defaultAccessDeniedHandler() {
final AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
accessDeniedHandler.setErrorPage("/403");
return accessDeniedHandler;
}
}
@Bean(name = {"defaultAuthenticationManager", "authenticationManager"})
public AuthenticationManager defaultAuthenticationManager() throws Exception {
return new AuthenticationManagerBuilder(opp).userDetailsService(context.getBean(PlatformUserDetailsService.class)).passwordEncoder(new Md5PasswordEncoder()).and().build();
}
// @formatter:on
@Bean(name = { "defaultRedirectStrategy", "redirectStrategy" })
protected DefaultRedirectStrategy defaultRedirectStrategy() {
return new DefaultRedirectStrategy();
}
@Bean(name = { "httpSessionRequestCache", "requestCache" })
protected static HttpSessionRequestCache httpSessionRequestCache() {
return new WebHttpSessionRequestCache();
}
/* Remember-me services */
@Bean(name = { "defaultRememberMeAuthenticationFilter", "rememberMeAuthenticationFilter" })
protected RememberMeAuthenticationFilter defaultRememberMeAuthenticationFilter() throws Exception {
return new RememberMeAuthenticationFilter(defaultAuthenticationManager(), context.getBean(DefaultRememberMeServices.class));
}
@Bean(name = { "defaultRememberMeAuthenticationProvider", "rememberMeAuthenticationProvider" })
protected RememberMeAuthenticationProvider defaultRememberMeAuthenticationProvider() {
return new RememberMeAuthenticationProvider("storefront");
}
}
然后是REST web-config:
@Order(value = 1)
public class RestServicesWebConfig implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
webCtx.register(RestServicesSecurityConfig.class);
webCtx.register(RestServicesConfig.class);
servletContext.addListener(new RequestContextListener());
servletContext.addListener(new HttpSessionMutexListener());
/* Spring REST Delegating Dispatcher Servlet */
Servlet restDispatcherServlet = new RepositoryRestDispatcherServlet(webCtx);
ServletRegistration.Dynamic restDispatcherServletReg = servletContext.addServlet("restDispatcherServlet", restDispatcherServlet);
restDispatcherServletReg.setLoadOnStartup(1);
restDispatcherServletReg.addMapping("/rest/*");
/* Character Encoding Filter */
FilterRegistration charEncodingfilterReg = servletContext.addFilter("restCharacterEncodingFilter", CharacterEncodingFilter.class);
charEncodingfilterReg.setInitParameter("encoding", "UTF-8");
charEncodingfilterReg.setInitParameter("forceEncoding", "true");
charEncodingfilterReg.addMappingForServletNames(null, false, restDispatcherServletReg.getName());
FilterRegistration corsFilter = servletContext.addFilter("corsFilter", CorsFilter.class);
corsFilter.addMappingForUrlPatterns(null, false, "/*");
/* Spring Security Delegating Filter */
FilterRegistration springSecurityFilterChainReg = servletContext.getFilterRegistration("springSecurityFilterChain");
springSecurityFilterChainReg.addMappingForServletNames(EnumSet.<DispatcherType>of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC), false, restDispatcherServletReg.getName());
}
}
和其余模块的安全配置:
@Order(3)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class RestServicesSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ObjectPostProcessor<Object> opp;
@Resource
public ApplicationContext context;
@Resource(name = PlatformUserDetailsService.NAME)
private PlatformUserDetailsService platformUserDetailsService;
// @formatter:off
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.antMatcher("/rest/**")
.exceptionHandling()
.authenticationEntryPoint(defaultDigestAuthenticationEntryPoint()).and()
.authorizeRequests()
.anyRequest().authenticated().and()
.requiresChannel()
.antMatchers("/rest/**").requiresSecure().and()
.logout()
.logoutUrl("/logout").and()
.addFilter(defaultDigestAuthenticationFilter());
}
// @formatter:on
/* Digest authentication */
@Bean(name = { "defaultDigestAuthenticationFilter", "digestFilter" })
protected DigestAuthenticationFilter defaultDigestAuthenticationFilter() {
DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
filter.setUserDetailsService(context.getBean(PlatformUserDetailsService.class));
filter.setAuthenticationEntryPoint(defaultDigestAuthenticationEntryPoint());
return filter;
}
@Bean(name = { "defaultDigestAuthenticationEntryPoint", "digestEntryPoint" })
protected DigestAuthenticationEntryPoint defaultDigestAuthenticationEntryPoint() {
DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint();
entryPoint.setKey("key");
entryPoint.setRealmName("Contacts Realm via Digest Authentication");
entryPoint.setNonceValiditySeconds(10);
return entryPoint;
}
@Bean(name = { "defaultRestLoginAuthenticationSuccessHandler", "restLoginAuthenticationSuccessHandler" })
protected AuthenticationSuccessHandler defaultRestLoginAuthenticationSuccessHandler() {
return new RestAuthenticationSuccessHandler();
}
@Bean(name = {"defaultAuthenticationManager", "authenticationManager"})
public AuthenticationManager defaultAuthenticationManager() throws Exception {
return new AuthenticationManagerBuilder(opp).userDetailsService(context.getBean(PlatformUserDetailsService.class)).passwordEncoder(new Md5PasswordEncoder()).and().build();
}
}