Skip to content

Instantly share code, notes, and snippets.

@anthavio
Last active July 13, 2018 14:15
Show Gist options
  • Select an option

  • Save anthavio/9748558 to your computer and use it in GitHub Desktop.

Select an option

Save anthavio/9748558 to your computer and use it in GitHub Desktop.

Revisions

  1. anthavio revised this gist Mar 24, 2014. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions WebappSpringConfig.java
    Original file line number Diff line number Diff line change
    @@ -57,17 +57,17 @@ public SecurityFilterChain restSecurityChain(String pattern) throws Exception {
    }

    /**
    * We store SPD and LOOP credentials in confidential.properties
    * We store XXX and YYY credentials in confidential.properties
    */
    private AuthenticationManager buildRestAuthenticationManager() throws Exception {
    Collection<UserDetails> users = new ArrayList<>();
    String spdUsername = environment.getRequiredProperty("authenticate.xxx.username");
    String spdPassword = environment.getRequiredProperty("authenticate.xxx.password");
    users.add(new User(spdUsername, spdPassword, Arrays.asList(new SimpleGrantedAuthority("ROLE_XXX_REST"))));
    String xxxUsername = environment.getRequiredProperty("authenticate.xxx.username");
    String xxxPassword = environment.getRequiredProperty("authenticate.xxx.password");
    users.add(new User(xxxUsername, xxxPassword, Arrays.asList(new SimpleGrantedAuthority("ROLE_XXX_REST"))));

    String loopUsername = environment.getRequiredProperty("authenticate.yyy.username");
    String loopPassword = environment.getRequiredProperty("authenticate.yyy.password");
    users.add(new User(loopUsername, loopPassword, Arrays.asList(new SimpleGrantedAuthority("ROLE_YYY_REST"))));
    String yyyUsername = environment.getRequiredProperty("authenticate.yyy.username");
    String yyyPassword = environment.getRequiredProperty("authenticate.yyy.password");
    users.add(new User(yyyUsername, yyyPassword, Arrays.asList(new SimpleGrantedAuthority("ROLE_YYY_REST"))));

    InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager(users);

  2. anthavio revised this gist Mar 24, 2014. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions WebappSpringConfig.java
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,9 @@
    @PropertySource(CoreSpringConfig.PROPERTIES)
    public class WebappSpringConfig {

    @Autowired
    private Environment environment;

    /**
    * 'springSecurityFilterChain' is Magic ID and it is required by Spring Security DelegatingFilterProxy in web.xml
    *
  3. anthavio revised this gist Mar 24, 2014. 1 changed file with 0 additions and 355 deletions.
    355 changes: 0 additions & 355 deletions spring-securiy-3.0.xml
    Original file line number Diff line number Diff line change
    @@ -1,355 +0,0 @@
    <?xml version="1.0" encoding="UTF-8"?>
    <beans
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:ctx="http://www.springframework.org/schema/context"
    xmlns:sec="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <!--
    http://static.springsource.org/spring-security/site/docs/3.0.x/reference/security-filter-chain.html
    http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#filter-stack
    -->
    <bean id="SpringSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <sec:filter-chain-map path-type="ant">
    <!--
    <sec:filter-chain pattern="/**" filters="none"/>
    -->
    <sec:filter-chain pattern="/js/**" filters="none"/>
    <sec:filter-chain pattern="/images/**" filters="none"/>
    <sec:filter-chain pattern="/css/**" filters="none"/>

    <sec:filter-chain pattern="/ws/cert/**" filters="
    WsSecurityContextPersistenceFilter,
    X509AuthenticationFilter,
    Http403ExceptionTranslationFilter,
    FilterSecurityInterceptor" />
    <sec:filter-chain pattern="/ws/basic/**" filters="
    WsSecurityContextPersistenceFilter,
    BasicAuthenticationFilter,
    BasicAuthenticationExceptionTranslationFilter,
    FilterSecurityInterceptor" />

    <sec:filter-chain pattern="/ui/access-denied.htm" filters="none"/>

    <sec:filter-chain pattern="/ui/**" filters="
    UiSecurityContextPersistenceFilter,
    LogoutFilter,
    NtlmExceptionTranslationFilter,
    NtlmFilter,
    FilterSecurityInterceptor" />
    </sec:filter-chain-map>

    <!--
    <sec:filter-chain pattern="/ui/**" filters="
    UiSecurityContextPersistenceFilter,
    LogoutFilter,
    FormLoginFilter,
    AnonymousAuthenticationFilter,
    FormExceptionTranslationFilter,
    FilterSecurityInterceptor" />
    -->

    </bean>

    <!-- http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-web-filters.html -->
    <bean id="FilterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="FullAuthenticationManager"/>
    <property name="accessDecisionManager" ref="WebAccessDecisionManager"/>
    <property name="messageSource" ref="messageSource"/>

    <property name="securityMetadataSource">
    <sec:filter-security-metadata-source path-type="ant" use-expressions="false">
    <sec:intercept-url pattern="/" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/welcome*" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/account/login*" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/j_spring_security_check" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/access-denied.htm" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/**" access="ROLE_AUTHENTICATED" />
    </sec:filter-security-metadata-source>
    </property>
    </bean>

    <bean id="FormExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint">
    <bean id="FormAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <property name="loginFormUrl" value="/ui/account/login.htm"/>
    </bean>
    </property>
    <property name="accessDeniedHandler" ref="AccessDeniedHandler"/>
    </bean>

    <bean id="AccessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
    <property name="errorPage" value="/ui/access-denied.htm"/>
    </bean>

    <!--
    <bean id="SessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
    <property name="authenticationFailureHandler">
    <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/account/login.htm?login_error=1"/>
    </bean>
    </property>
    </bean>
    -->

    <bean id="UiSecurityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name="securityContextRepository">
    <bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
    <property name="allowSessionCreation" value="true" />
    </bean>
    </property>
    </bean>

    <bean id="NtlmFilter" class="org.springframework.security.ui.ntlm.NtlmAuthenticationFilter">
    <property name="retryOnAuthFailure" value="false" />
    <property name="stripDomain" value="true"/>
    <property name="defaultDomain" value="${jcifs.smb.client.domain}"/>
    <property name="netbiosWINS" value="${jcifs.netbios.wins}"/>
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref bean="LdapAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    </bean>

    <!-- Providers are checked sequentially, if it is problem multiple dedicated AuthenticationManages is an option -->
    <bean id="FullAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="PreAuthenticatedAuthenticationProvider"/>
    <ref local="BasicAuthenticationProvider"/>
    <ref bean="LdapAuthenticationProvider"/>
    </list>
    </property>
    </bean>

    <bean id="NullRequestCacheAwareFilter" class="org.springframework.security.web.savedrequest.NullRequestCache"/>

    <bean id="NtlmEntryPoint" class="org.springframework.security.ui.ntlm.NtlmAuthenticationFilterEntryPoint">
    <property name="authenticationFailureUrl" value="/ui/access-denied.htm"/>
    </bean>

    <bean id="NtlmExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint" ref="NtlmEntryPoint"/>
    </bean>

    <bean id="FormLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="BasicAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="filterProcessesUrl" value="/ui/j_spring_security_check"/>
    <property name="authenticationSuccessHandler">
    <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    </bean>
    </property>
    <property name="authenticationFailureHandler">
    <bean class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/ui/account/login.htm?authfailed=true"/>
    <property name="exceptionMappings">
    <map>
    <entry key="org.springframework.security.core.userdetails.UsernameNotFoundException" value="/ui/account/login.htm?errusername=true"/>
    <entry key="org.springframework.security.authentication.BadCredentialsException" value="/ui/account/login.htm?errpassword=true"/>
    <entry key="org.springframework.security.authentication.CredentialsExpiredException" value="/ui/account/login.htm?newpassword=true"/>
    <entry key="org.springframework.security.authentication.LockedException" value="/ui/account/login.htm?acclocked=true"/>
    <entry key="org.springframework.security.authentication.DisabledException" value="/ui/account/login.htm?accdisabled=true"/>
    </map>
    </property>
    </bean>
    </property>
    <property name="sessionAuthenticationStrategy">
    <bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
    <constructor-arg ref="SessionRegistry"/>
    <property name="maximumSessions" value="1"/>
    <property name="exceptionIfMaximumExceeded" value="true"/>
    </bean>
    </property>
    </bean>

    <bean id="SessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>

    <bean id="LogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg name="logoutSuccessHandler" ref="LogoutSuccessHandler"/>
    <constructor-arg name="handlers">
    <array>
    <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
    <property name="invalidateHttpSession" value="true"/>
    </bean>
    </array>
    </constructor-arg>
    <property name="filterProcessesUrl" value="/ui/account/logout"/>
    </bean>

    <bean id="LogoutSuccessHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
    <!--
    <property name="defaultTargetUrl" value="/ui/account/login.htm?loggedout=true"/>
    -->
    <property name="defaultTargetUrl" value="/ui/index.htm"/>
    </bean>

    <!-- 12. Anonymous Authentication http://static.springsource.org/spring-security/site/docs/3.0.x/reference/anonymous.html -->

    <bean id="AnonymousAuthenticationFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
    <property name="key" value="anonymous-key"/>
    <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS"/>
    </bean>

    <!-- WebSvc -->

    <bean id="WsSecurityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name="securityContextRepository">
    <bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
    <property name="allowSessionCreation" value="false" />
    </bean>
    </property>
    </bean>

    <bean id="X509AuthenticationFilter" class="org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter">
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="PreAuthenticatedAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="principalExtractor">
    <bean class="org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor">
    <property name="subjectDnRegex" value="CN=([^,]+)"/>
    </bean>
    </property>
    </bean>

    <bean id="BasicAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="BasicAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="authenticationEntryPoint" ref="BasicAuthenticationEntryPoint"/>
    </bean>

    <bean id="BasicAuthenticationExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint" ref="BasicAuthenticationEntryPoint" />
    <property name="accessDeniedHandler">
    <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl" />
    </property>
    </bean>

    <bean id="BasicAuthenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
    <property name="realmName" value="MyGreatRealm"/>
    </bean>

    <bean id="BasicAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="WsUserDetailsService"/>
    <property name="hideUserNotFoundExceptions" value="false"/>
    </bean>

    <bean id="PreAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
    <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    <property name="userDetailsService" ref="WsUserDetailsService"/>
    </bean>
    </property>
    </bean>

    <sec:user-service id="WsUserDetailsService">
    <!-- x509 certificate -->
    <sec:user name="localhost" password="" authorities="ROLE_SOMETHING, ROLE_WHATEVER, ROLE_REPORTER, ROLE_ADMIN"/>
    <!-- http basic -->
    <sec:user name="wsclient" password="password" authorities="ROLE_SOMETHING, ROLE_WHATEVER, ROLE_REPORTER, ROLE_ADMIN" />
    </sec:user-service>

    <bean id="Http403ExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint">
    <bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
    </property>
    </bean>

    <!-- common -->

    <bean id="WebAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
    <list>
    <bean id="RoleHierarchyVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="AppRoleHierarchy"/>
    <property name="rolePrefix" value="ROLE_"/>
    </bean>
    <bean id="WebPreInvocationAuthorizationAdviceVoter" class="org.springframework.security.web.access.expression.WebExpressionVoter">
    <property name="expressionHandler" ref="WebExpressionHandler" />
    </bean>
    </list>
    </property>
    </bean>

    <bean id="WebExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
    <property name="roleHierarchy" ref="AppRoleHierarchy" />
    </bean>

    <bean id="AppRoleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
    <value>
    ROLE_SOMETHING > ROLE_AUTHENTICATED
    ROLE_WHATEVER > ROLE_AUTHENTICATED
    ROLE_REPORTER > ROLE_AUTHENTICATED
    ROLE_ADMIN > ROLE_AUTHENTICATED
    </value>
    </property>
    </bean>

    <bean id="LdapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <constructor-arg>
    <bean class="org.springframework.security.ui.ntlm.ldap.authenticator.NtlmAwareLdapAuthenticator">
    <constructor-arg ref="LdapContextSource"/>
    <property name="userSearch">
    <bean id="LdapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg index="0" value="${ldap.search.base}"/>
    <constructor-arg index="1" value="${ldap.search.auth.user.filter}"/>
    <constructor-arg index="2" ref="LdapContextSource" />
    </bean>
    </property>
    </bean>
    </constructor-arg>
    <constructor-arg>
    <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <constructor-arg ref="LdapContextSource" />
    <constructor-arg value="${ldap.search.base}" />
    <property name="searchSubtree" value="true"/>
    <property name="groupSearchFilter" value="${ldap.search.auth.role.filter}"/>
    <property name="rolePrefix" value=""/>
    <property name="convertToUpperCase" value="false"/>
    </bean>
    </constructor-arg>
    <property name="userDetailsContextMapper">
    <bean class="x.y.z.services.user.UserDetailsContextMapper">
    <property name="emailAttribute" value="${ldap.user.email.attribute}"/>
    </bean>
    </property>
    </bean>

    <bean id="LdapContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <constructor-arg value="${ldap.bind.url}"/>
    <property name="userDn" value="${ldap.bind.userDn}"/>
    <property name="password" value="${ldap.bind.password}"/>

    </bean>
    </beans>
  4. anthavio revised this gist Mar 24, 2014. 1 changed file with 171 additions and 0 deletions.
    171 changes: 171 additions & 0 deletions WebappSpringConfig.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,171 @@
    @Configuration
    @PropertySource(CoreSpringConfig.PROPERTIES)
    public class WebappSpringConfig {

    /**
    * 'springSecurityFilterChain' is Magic ID and it is required by Spring Security DelegatingFilterProxy in web.xml
    *
    * We cannot use @EnableWebSecurity with WebSecurityConfigurerAdapter because they allows only single
    * SecurityFilterChain fore whole web application, but we have 2 chains
    * - Active Directory/LDAP backed for Admin web application
    * - Properties backed for REST endpoints
    */
    @Bean(name = "springSecurityFilterChain")
    public FilterChainProxy springSecurityFilterChain() throws Exception {
    List<SecurityFilterChain> filterChains = new ArrayList<>();
    filterChains.add(restSecurityChain("/api/**"));
    filterChains.add(adminSecurityChain("/admin/**"));
    FilterChainProxy filterChainProxy = new FilterChainProxy(filterChains);
    return filterChainProxy;
    }

    public SecurityFilterChain restSecurityChain(String pattern) throws Exception {
    //Don't create session for REST caller
    SecurityContextPersistenceFilter persistenceFilter = buildPersistenceFilter(false);

    AuthenticationManager authenticationManager = buildRestAuthenticationManager();

    BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
    entryPoint.setRealmName("Rest Realm");
    BasicAuthenticationFilter basicFilter = new BasicAuthenticationFilter(authenticationManager, entryPoint);
    basicFilter.afterPropertiesSet();

    AccessDecisionManager accessDecisionManager = buildAccessDecisionManager();

    AnonymousAuthenticationFilter anonymousFilter = buildAnonymousAuthenticationFilter("ROLE_ANONYMOUS");

    FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
    securityInterceptor.setAuthenticationManager(authenticationManager);
    securityInterceptor.setAccessDecisionManager(accessDecisionManager);

    LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>();
    requestMap.put(AntMatcher("/api/xxx/**"), SecurityConfig.createList("ROLE_XXX_REST"));
    requestMap.put(AntMatcher("/api/yyy/**"), SecurityConfig.createList("ROLE_YYY_REST"));
    DefaultFilterInvocationSecurityMetadataSource metadataSource = new DefaultFilterInvocationSecurityMetadataSource(
    requestMap);
    securityInterceptor.setSecurityMetadataSource(metadataSource);
    securityInterceptor.afterPropertiesSet();

    //Send 403 directly to REST caller - Http403ForbiddenEntryPoint
    ExceptionTranslationFilter exceptionFilter = new ExceptionTranslationFilter(entryPoint);

    return new DefaultSecurityFilterChain(AntMatcher(pattern), persistenceFilter, basicFilter, anonymousFilter,
    exceptionFilter, securityInterceptor);
    }

    /**
    * We store SPD and LOOP credentials in confidential.properties
    */
    private AuthenticationManager buildRestAuthenticationManager() throws Exception {
    Collection<UserDetails> users = new ArrayList<>();
    String spdUsername = environment.getRequiredProperty("authenticate.xxx.username");
    String spdPassword = environment.getRequiredProperty("authenticate.xxx.password");
    users.add(new User(spdUsername, spdPassword, Arrays.asList(new SimpleGrantedAuthority("ROLE_XXX_REST"))));

    String loopUsername = environment.getRequiredProperty("authenticate.yyy.username");
    String loopPassword = environment.getRequiredProperty("authenticate.yyy.password");
    users.add(new User(loopUsername, loopPassword, Arrays.asList(new SimpleGrantedAuthority("ROLE_YYY_REST"))));

    InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager(users);

    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService);
    authenticationProvider.afterPropertiesSet();

    AuthenticationManager authenticationManager = new ProviderManager(
    Arrays.asList((AuthenticationProvider) authenticationProvider));
    return authenticationManager;
    }

    private AccessDecisionManager buildAccessDecisionManager() {
    List<AccessDecisionVoter> voters = new ArrayList<>();
    voters.add(new RoleVoter());//RoleHierarchyVoter
    //voters.add(new WebExpressionVoter());
    AccessDecisionManager accessDecisionManager = new AffirmativeBased(voters);
    return accessDecisionManager;
    }

    public SecurityFilterChain adminSecurityChain(String pattern) throws Exception {
    //Allow session for Interactive users
    SecurityContextPersistenceFilter persistenceFilter = buildPersistenceFilter(true);

    //Interactive user can logout
    SimpleUrlLogoutSuccessHandler successHandler = new SimpleUrlLogoutSuccessHandler();
    successHandler.setDefaultTargetUrl("/");
    SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
    logoutHandler.setClearAuthentication(true);
    logoutHandler.setInvalidateHttpSession(true);
    LogoutFilter logoutFilter = new LogoutFilter(successHandler, logoutHandler);

    //Build AuthenticationManager from provided LDAP AuthenticationProvider
    AuthenticationManager authenticationManager = new ProviderManager(Arrays.asList(adminAuthenticationProvider()));

    BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
    entryPoint.setRealmName("Admin Realm");
    BasicAuthenticationFilter basicFilter = new BasicAuthenticationFilter(authenticationManager, entryPoint);
    basicFilter.afterPropertiesSet();

    AnonymousAuthenticationFilter anonymousFilter = buildAnonymousAuthenticationFilter("ROLE_ANONYMOUS");

    AccessDecisionManager accessDecisionManager = buildAccessDecisionManager();

    FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
    securityInterceptor.setAuthenticationManager(authenticationManager);
    securityInterceptor.setAccessDecisionManager(accessDecisionManager);

    //Single role to cover whole application
    LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<>();
    requestMap.put(AntMatcher("/admin/**"), SecurityConfig.createList("ROLE_ADMIN"));
    DefaultFilterInvocationSecurityMetadataSource metadataSource = new DefaultFilterInvocationSecurityMetadataSource(
    requestMap);
    securityInterceptor.setSecurityMetadataSource(metadataSource);
    securityInterceptor.afterPropertiesSet();

    //Send BASIC challenge to interactive users
    ExceptionTranslationFilter exceptionFilter = new ExceptionTranslationFilter(entryPoint);

    //org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5d4971e
    //org.springframework.security.web.context.SecurityContextPersistenceFilter@39f7e368
    //org.springframework.security.web.header.HeaderWriterFilter@392a028f
    //org.springframework.security.web.authentication.logout.LogoutFilter@7dab317
    //org.springframework.security.web.authentication.www.BasicAuthenticationFilter@240b6882
    //org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5c72a676
    //org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@14728025
    //org.springframework.security.web.authentication.AnonymousAuthenticationFilter@480d358f
    //org.springframework.security.web.session.SessionManagementFilter@f72ebc1
    //org.springframework.security.web.access.ExceptionTranslationFilter@6f4809f6
    //org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3dbe15bc

    return new DefaultSecurityFilterChain(AntMatcher(pattern), persistenceFilter, logoutFilter, basicFilter,
    anonymousFilter, exceptionFilter, securityInterceptor);
    }

    private AuthenticationProvider adminAuthenticationProvider() {
    String domain = environment.getRequiredProperty("ldap.domain");
    String url = environment.getRequiredProperty("ldap.url");
    ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(domain, url);
    provider.setAuthoritiesMapper(new SimpleAuthorityMapper()); //add ROLE_ prefix
    return provider;
    }

    public static RequestMatcher AntMatcher(String pattern) {
    if (pattern == null || pattern.isEmpty()) {
    throw new IllegalArgumentException("Null or empty pattern");
    }
    return new AntPathRequestMatcher(pattern);
    }

    private AnonymousAuthenticationFilter buildAnonymousAuthenticationFilter(String anonymousRole) {
    AnonymousAuthenticationFilter filter = new AnonymousAuthenticationFilter("anonymous-key", "AnonymousUser",
    AuthorityUtils.createAuthorityList(anonymousRole));
    return filter;
    }

    private SecurityContextPersistenceFilter buildPersistenceFilter(boolean allowSessions) throws ServletException {
    HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository();
    repository.setAllowSessionCreation(allowSessions);
    SecurityContextPersistenceFilter persistenceFilter = new SecurityContextPersistenceFilter(repository);
    persistenceFilter.afterPropertiesSet();
    return persistenceFilter;
    }
    }
  5. anthavio created this gist Mar 24, 2014.
    355 changes: 355 additions & 0 deletions spring-securiy-3.0.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,355 @@
    <?xml version="1.0" encoding="UTF-8"?>
    <beans
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:ctx="http://www.springframework.org/schema/context"
    xmlns:sec="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <!--
    http://static.springsource.org/spring-security/site/docs/3.0.x/reference/security-filter-chain.html
    http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#filter-stack
    -->
    <bean id="SpringSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <sec:filter-chain-map path-type="ant">
    <!--
    <sec:filter-chain pattern="/**" filters="none"/>
    -->
    <sec:filter-chain pattern="/js/**" filters="none"/>
    <sec:filter-chain pattern="/images/**" filters="none"/>
    <sec:filter-chain pattern="/css/**" filters="none"/>

    <sec:filter-chain pattern="/ws/cert/**" filters="
    WsSecurityContextPersistenceFilter,
    X509AuthenticationFilter,
    Http403ExceptionTranslationFilter,
    FilterSecurityInterceptor" />
    <sec:filter-chain pattern="/ws/basic/**" filters="
    WsSecurityContextPersistenceFilter,
    BasicAuthenticationFilter,
    BasicAuthenticationExceptionTranslationFilter,
    FilterSecurityInterceptor" />

    <sec:filter-chain pattern="/ui/access-denied.htm" filters="none"/>

    <sec:filter-chain pattern="/ui/**" filters="
    UiSecurityContextPersistenceFilter,
    LogoutFilter,
    NtlmExceptionTranslationFilter,
    NtlmFilter,
    FilterSecurityInterceptor" />
    </sec:filter-chain-map>

    <!--
    <sec:filter-chain pattern="/ui/**" filters="
    UiSecurityContextPersistenceFilter,
    LogoutFilter,
    FormLoginFilter,
    AnonymousAuthenticationFilter,
    FormExceptionTranslationFilter,
    FilterSecurityInterceptor" />
    -->

    </bean>

    <!-- http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-web-filters.html -->
    <bean id="FilterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="FullAuthenticationManager"/>
    <property name="accessDecisionManager" ref="WebAccessDecisionManager"/>
    <property name="messageSource" ref="messageSource"/>

    <property name="securityMetadataSource">
    <sec:filter-security-metadata-source path-type="ant" use-expressions="false">
    <sec:intercept-url pattern="/" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/welcome*" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/account/login*" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/j_spring_security_check" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/ui/access-denied.htm" access="ROLE_ANONYMOUS,ROLE_AUTHENTICATED" />
    <sec:intercept-url pattern="/**" access="ROLE_AUTHENTICATED" />
    </sec:filter-security-metadata-source>
    </property>
    </bean>

    <bean id="FormExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint">
    <bean id="FormAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <property name="loginFormUrl" value="/ui/account/login.htm"/>
    </bean>
    </property>
    <property name="accessDeniedHandler" ref="AccessDeniedHandler"/>
    </bean>

    <bean id="AccessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
    <property name="errorPage" value="/ui/access-denied.htm"/>
    </bean>

    <!--
    <bean id="SessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
    <property name="authenticationFailureHandler">
    <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/account/login.htm?login_error=1"/>
    </bean>
    </property>
    </bean>
    -->

    <bean id="UiSecurityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name="securityContextRepository">
    <bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
    <property name="allowSessionCreation" value="true" />
    </bean>
    </property>
    </bean>

    <bean id="NtlmFilter" class="org.springframework.security.ui.ntlm.NtlmAuthenticationFilter">
    <property name="retryOnAuthFailure" value="false" />
    <property name="stripDomain" value="true"/>
    <property name="defaultDomain" value="${jcifs.smb.client.domain}"/>
    <property name="netbiosWINS" value="${jcifs.netbios.wins}"/>
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref bean="LdapAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    </bean>

    <!-- Providers are checked sequentially, if it is problem multiple dedicated AuthenticationManages is an option -->
    <bean id="FullAuthenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="PreAuthenticatedAuthenticationProvider"/>
    <ref local="BasicAuthenticationProvider"/>
    <ref bean="LdapAuthenticationProvider"/>
    </list>
    </property>
    </bean>

    <bean id="NullRequestCacheAwareFilter" class="org.springframework.security.web.savedrequest.NullRequestCache"/>

    <bean id="NtlmEntryPoint" class="org.springframework.security.ui.ntlm.NtlmAuthenticationFilterEntryPoint">
    <property name="authenticationFailureUrl" value="/ui/access-denied.htm"/>
    </bean>

    <bean id="NtlmExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint" ref="NtlmEntryPoint"/>
    </bean>

    <bean id="FormLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="BasicAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="filterProcessesUrl" value="/ui/j_spring_security_check"/>
    <property name="authenticationSuccessHandler">
    <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    </bean>
    </property>
    <property name="authenticationFailureHandler">
    <bean class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/ui/account/login.htm?authfailed=true"/>
    <property name="exceptionMappings">
    <map>
    <entry key="org.springframework.security.core.userdetails.UsernameNotFoundException" value="/ui/account/login.htm?errusername=true"/>
    <entry key="org.springframework.security.authentication.BadCredentialsException" value="/ui/account/login.htm?errpassword=true"/>
    <entry key="org.springframework.security.authentication.CredentialsExpiredException" value="/ui/account/login.htm?newpassword=true"/>
    <entry key="org.springframework.security.authentication.LockedException" value="/ui/account/login.htm?acclocked=true"/>
    <entry key="org.springframework.security.authentication.DisabledException" value="/ui/account/login.htm?accdisabled=true"/>
    </map>
    </property>
    </bean>
    </property>
    <property name="sessionAuthenticationStrategy">
    <bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
    <constructor-arg ref="SessionRegistry"/>
    <property name="maximumSessions" value="1"/>
    <property name="exceptionIfMaximumExceeded" value="true"/>
    </bean>
    </property>
    </bean>

    <bean id="SessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>

    <bean id="LogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg name="logoutSuccessHandler" ref="LogoutSuccessHandler"/>
    <constructor-arg name="handlers">
    <array>
    <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
    <property name="invalidateHttpSession" value="true"/>
    </bean>
    </array>
    </constructor-arg>
    <property name="filterProcessesUrl" value="/ui/account/logout"/>
    </bean>

    <bean id="LogoutSuccessHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
    <!--
    <property name="defaultTargetUrl" value="/ui/account/login.htm?loggedout=true"/>
    -->
    <property name="defaultTargetUrl" value="/ui/index.htm"/>
    </bean>

    <!-- 12. Anonymous Authentication http://static.springsource.org/spring-security/site/docs/3.0.x/reference/anonymous.html -->

    <bean id="AnonymousAuthenticationFilter" class="org.springframework.security.web.authentication.AnonymousAuthenticationFilter">
    <property name="key" value="anonymous-key"/>
    <property name="userAttribute" value="anonymous,ROLE_ANONYMOUS"/>
    </bean>

    <!-- WebSvc -->

    <bean id="WsSecurityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name="securityContextRepository">
    <bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository">
    <property name="allowSessionCreation" value="false" />
    </bean>
    </property>
    </bean>

    <bean id="X509AuthenticationFilter" class="org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter">
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="PreAuthenticatedAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="principalExtractor">
    <bean class="org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor">
    <property name="subjectDnRegex" value="CN=([^,]+)"/>
    </bean>
    </property>
    </bean>

    <bean id="BasicAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
    <property name="authenticationManager">
    <bean class="org.springframework.security.authentication.ProviderManager">
    <property name="providers">
    <list>
    <ref local="BasicAuthenticationProvider"/>
    </list>
    </property>
    </bean>
    </property>
    <property name="authenticationEntryPoint" ref="BasicAuthenticationEntryPoint"/>
    </bean>

    <bean id="BasicAuthenticationExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint" ref="BasicAuthenticationEntryPoint" />
    <property name="accessDeniedHandler">
    <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl" />
    </property>
    </bean>

    <bean id="BasicAuthenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
    <property name="realmName" value="MyGreatRealm"/>
    </bean>

    <bean id="BasicAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="WsUserDetailsService"/>
    <property name="hideUserNotFoundExceptions" value="false"/>
    </bean>

    <bean id="PreAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
    <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    <property name="userDetailsService" ref="WsUserDetailsService"/>
    </bean>
    </property>
    </bean>

    <sec:user-service id="WsUserDetailsService">
    <!-- x509 certificate -->
    <sec:user name="localhost" password="" authorities="ROLE_SOMETHING, ROLE_WHATEVER, ROLE_REPORTER, ROLE_ADMIN"/>
    <!-- http basic -->
    <sec:user name="wsclient" password="password" authorities="ROLE_SOMETHING, ROLE_WHATEVER, ROLE_REPORTER, ROLE_ADMIN" />
    </sec:user-service>

    <bean id="Http403ExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint">
    <bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
    </property>
    </bean>

    <!-- common -->

    <bean id="WebAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
    <list>
    <bean id="RoleHierarchyVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="AppRoleHierarchy"/>
    <property name="rolePrefix" value="ROLE_"/>
    </bean>
    <bean id="WebPreInvocationAuthorizationAdviceVoter" class="org.springframework.security.web.access.expression.WebExpressionVoter">
    <property name="expressionHandler" ref="WebExpressionHandler" />
    </bean>
    </list>
    </property>
    </bean>

    <bean id="WebExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
    <property name="roleHierarchy" ref="AppRoleHierarchy" />
    </bean>

    <bean id="AppRoleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
    <value>
    ROLE_SOMETHING > ROLE_AUTHENTICATED
    ROLE_WHATEVER > ROLE_AUTHENTICATED
    ROLE_REPORTER > ROLE_AUTHENTICATED
    ROLE_ADMIN > ROLE_AUTHENTICATED
    </value>
    </property>
    </bean>

    <bean id="LdapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <constructor-arg>
    <bean class="org.springframework.security.ui.ntlm.ldap.authenticator.NtlmAwareLdapAuthenticator">
    <constructor-arg ref="LdapContextSource"/>
    <property name="userSearch">
    <bean id="LdapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg index="0" value="${ldap.search.base}"/>
    <constructor-arg index="1" value="${ldap.search.auth.user.filter}"/>
    <constructor-arg index="2" ref="LdapContextSource" />
    </bean>
    </property>
    </bean>
    </constructor-arg>
    <constructor-arg>
    <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <constructor-arg ref="LdapContextSource" />
    <constructor-arg value="${ldap.search.base}" />
    <property name="searchSubtree" value="true"/>
    <property name="groupSearchFilter" value="${ldap.search.auth.role.filter}"/>
    <property name="rolePrefix" value=""/>
    <property name="convertToUpperCase" value="false"/>
    </bean>
    </constructor-arg>
    <property name="userDetailsContextMapper">
    <bean class="x.y.z.services.user.UserDetailsContextMapper">
    <property name="emailAttribute" value="${ldap.user.email.attribute}"/>
    </bean>
    </property>
    </bean>

    <bean id="LdapContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <constructor-arg value="${ldap.bind.url}"/>
    <property name="userDn" value="${ldap.bind.userDn}"/>
    <property name="password" value="${ldap.bind.password}"/>

    </bean>
    </beans>