Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package de.knightsoftnet.validationexample.server.spring; import de.knightsoftnet.validationexample.client.ui.navigation.NameTokens; import de.knightsoftnet.validationexample.shared.AppResourcePaths; import de.knightsoftnet.validators.server.security.AuthFailureHandler; import de.knightsoftnet.validators.server.security.AuthSuccessHandler; import de.knightsoftnet.validators.server.security.CsrfCookieHandler; import de.knightsoftnet.validators.server.security.HttpAuthenticationEntryPoint; import de.knightsoftnet.validators.server.security.HttpLogoutSuccessHandler; import de.knightsoftnet.validators.shared.Parameters; import de.knightsoftnet.validators.shared.ResourcePaths; import de.knightsoftnet.validators.shared.ResourcePaths.PhoneNumber; import de.knightsoftnet.validators.shared.ResourcePaths.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.csrf.CsrfFilter; import org.springframework.security.web.csrf.CsrfTokenRepository; import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * configuration for spring security. * * @author Manfred Tremmel */ @Configuration @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) @EntityScan("de.knightsoftnet.validationexample.shared.models") @ComponentScan(basePackages = { "de.knightsoftnet.validationexample.shared.models", "de.knightsoftnet.validationexample.server", "de.knightsoftnet.validators.server" }) @EnableTransactionManagement @EnableJpaRepositories(basePackages = { "de.knightsoftnet.validationexample.shared.models", "de.knightsoftnet.validationexample.server.repository" }) @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private static final String LOGIN_PATH = User.ROOT + User.LOGIN; @Autowired private HttpAuthenticationEntryPoint authenticationEntryPoint; @Autowired private AuthSuccessHandler authSuccessHandler; @Autowired private AuthFailureHandler authFailureHandler; @Autowired private HttpLogoutSuccessHandler logoutSuccessHandler; @Autowired private CsrfCookieHandler csrfCookieHandler; /** * configure urls which are ignored by security. * * @param pweb web security config */ @Override public void configure(final WebSecurity pweb) throws Exception { // NOPMD pweb.ignoring() // .antMatchers("/", // "/index.html", // "/favicon.ico", // "/" + NameTokens.LOGIN, // "/" + NameTokens.SECRET + "/" + NameTokens.LOGIN, // "/" + NameTokens.LOGOUT, // "/" + NameTokens.SEPA, // "/" + NameTokens.ADDRESS, // "/" + NameTokens.PHONE_NUMBER, // "/" + NameTokens.SECRET, // "/" + NameTokens.SETTINGS, // "/gwtBeanValidatorsExample/**"); } /** * configure security settings. * * @param phttp http security */ @Override protected void configure(final HttpSecurity phttp) throws Exception { // NOPMD // csrf/xsrf protection phttp.csrf().csrfTokenRepository(this.csrfTokenRepository()) // .and().addFilterAfter(this.csrfHeaderFilter(), CsrfFilter.class) // .authorizeRequests() // // services without authentication .antMatchers(AppResourcePaths.PHONE_NUMBER, // AppResourcePaths.POSTAL_ADDRESS, // AppResourcePaths.SEPA, // PhoneNumber.ROOT + "/**") // .permitAll() // // all other requests need authentication .anyRequest().authenticated() // // handle not allowed access, delegate to authentication entry poing .and() // .exceptionHandling() // .authenticationEntryPoint(this.authenticationEntryPoint) // // login form handling .and() // .formLogin() // .permitAll().loginProcessingUrl(LOGIN_PATH) // .usernameParameter(Parameters.USERNAME) // .passwordParameter(Parameters.PASSWORD) // .successHandler(this.authSuccessHandler) // .failureHandler(this.authFailureHandler) // .and().logout().permitAll() // .logoutRequestMatcher(new AntPathRequestMatcher(LOGIN_PATH, "DELETE")) // .logoutSuccessHandler(this.logoutSuccessHandler) // .and() // .sessionManagement().maximumSessions(1); } @Configuration protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter { @Override public void init(final AuthenticationManagerBuilder auth) throws Exception { // NOPMD auth.ldapAuthentication().userDnPatterns("uid={0},ou=people").groupSearchBase("ou=groups") .contextSource().ldif("classpath:test-server.ldif"); } } private Filter csrfHeaderFilter() { return new OncePerRequestFilter() { @Override protected void doFilterInternal(final HttpServletRequest prequest, final HttpServletResponse presponse, final FilterChain pfilterChain) throws ServletException, IOException { WebSecurityConfig.this.csrfCookieHandler.setCookie(prequest, presponse); pfilterChain.doFilter(prequest, presponse); } }; } /** * define csrf header entry. * * @return csrf header entry */ @Bean public CsrfTokenRepository csrfTokenRepository() { final HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); repository.setHeaderName(ResourcePaths.XSRF_HEADER); return repository; } }