001/*
002 * Copyright 2012-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.h2;
018
019import org.h2.server.web.WebServlet;
020
021import org.springframework.beans.factory.annotation.Autowired;
022import org.springframework.boot.autoconfigure.AutoConfigureAfter;
023import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
024import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
025import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
026import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
027import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
028import org.springframework.boot.autoconfigure.security.SecurityAuthorizeMode;
029import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
030import org.springframework.boot.autoconfigure.security.SecurityProperties;
031import org.springframework.boot.context.properties.EnableConfigurationProperties;
032import org.springframework.boot.web.servlet.ServletRegistrationBean;
033import org.springframework.context.annotation.Bean;
034import org.springframework.context.annotation.Configuration;
035import org.springframework.core.annotation.Order;
036import org.springframework.security.config.annotation.ObjectPostProcessor;
037import org.springframework.security.config.annotation.web.builders.HttpSecurity;
038import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
039
040/**
041 * {@link EnableAutoConfiguration Auto-configuration} for H2's web console.
042 *
043 * @author Andy Wilkinson
044 * @author Marten Deinum
045 * @author Stephane Nicoll
046 * @since 1.3.0
047 */
048@Configuration
049@ConditionalOnWebApplication
050@ConditionalOnClass(WebServlet.class)
051@ConditionalOnProperty(prefix = "spring.h2.console", name = "enabled", havingValue = "true", matchIfMissing = false)
052@EnableConfigurationProperties(H2ConsoleProperties.class)
053@AutoConfigureAfter(SecurityAutoConfiguration.class)
054public class H2ConsoleAutoConfiguration {
055
056        private final H2ConsoleProperties properties;
057
058        public H2ConsoleAutoConfiguration(H2ConsoleProperties properties) {
059                this.properties = properties;
060        }
061
062        @Bean
063        public ServletRegistrationBean h2Console() {
064                String path = this.properties.getPath();
065                String urlMapping = (path.endsWith("/") ? path + "*" : path + "/*");
066                ServletRegistrationBean registration = new ServletRegistrationBean(
067                                new WebServlet(), urlMapping);
068                H2ConsoleProperties.Settings settings = this.properties.getSettings();
069                if (settings.isTrace()) {
070                        registration.addInitParameter("trace", "");
071                }
072                if (settings.isWebAllowOthers()) {
073                        registration.addInitParameter("webAllowOthers", "");
074                }
075                return registration;
076        }
077
078        @Configuration
079        @ConditionalOnClass(WebSecurityConfigurerAdapter.class)
080        @ConditionalOnBean(ObjectPostProcessor.class)
081        @ConditionalOnProperty(prefix = "security.basic", name = "enabled", matchIfMissing = true)
082        static class H2ConsoleSecurityConfiguration {
083
084                @Bean
085                public WebSecurityConfigurerAdapter h2ConsoleSecurityConfigurer() {
086                        return new H2ConsoleSecurityConfigurer();
087                }
088
089                @Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
090                private static class H2ConsoleSecurityConfigurer
091                                extends WebSecurityConfigurerAdapter {
092
093                        @Autowired
094                        private H2ConsoleProperties console;
095
096                        @Autowired
097                        private SecurityProperties security;
098
099                        @Override
100                        public void configure(HttpSecurity http) throws Exception {
101                                String path = this.console.getPath();
102                                String antPattern = (path.endsWith("/") ? path + "**" : path + "/**");
103                                HttpSecurity h2Console = http.antMatcher(antPattern);
104                                h2Console.csrf().disable();
105                                h2Console.httpBasic();
106                                h2Console.headers().frameOptions().sameOrigin();
107                                String[] roles = this.security.getUser().getRole().toArray(new String[0]);
108                                SecurityAuthorizeMode mode = this.security.getBasic().getAuthorizeMode();
109                                if (mode == null || mode == SecurityAuthorizeMode.ROLE) {
110                                        http.authorizeRequests().anyRequest().hasAnyRole(roles);
111                                }
112                                else if (mode == SecurityAuthorizeMode.AUTHENTICATED) {
113                                        http.authorizeRequests().anyRequest().authenticated();
114                                }
115                        }
116
117                }
118
119        }
120
121}