View Javadoc

1   package demo;
2   
3   import javax.servlet.Filter;
4   import javax.sql.DataSource;
5   
6   import org.springframework.beans.factory.annotation.Autowired;
7   import org.springframework.beans.factory.annotation.Qualifier;
8   import org.springframework.boot.SpringApplication;
9   import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
10  import org.springframework.boot.autoconfigure.security.SecurityProperties;
11  import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
12  import org.springframework.boot.context.embedded.FilterRegistrationBean;
13  import org.springframework.context.annotation.Bean;
14  import org.springframework.context.annotation.Configuration;
15  import org.springframework.context.annotation.DependsOn;
16  import org.springframework.context.annotation.ImportResource;
17  import org.springframework.core.Ordered;
18  import org.springframework.core.annotation.Order;
19  import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
20  import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
21  import org.springframework.security.config.annotation.web.builders.HttpSecurity;
22  import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
23  import org.springframework.security.config.http.SessionCreationPolicy;
24  import org.springframework.security.core.userdetails.UserDetailsService;
25  import org.springframework.security.oauth2.provider.ClientDetailsService;
26  import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService;
27  import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
28  import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
29  import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
30  import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint;
31  import org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint;
32  import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
33  import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
34  import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
35  import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
36  import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
37  import org.springframework.security.web.AuthenticationEntryPoint;
38  import org.springframework.security.web.access.AccessDeniedHandler;
39  import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
40  import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
41  import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
42  import org.springframework.web.bind.annotation.RequestMapping;
43  import org.springframework.web.bind.annotation.RestController;
44  
45  @Configuration
46  @EnableAutoConfiguration
47  @RestController
48  @ImportResource("classpath:/application.xml")
49  public class Application {
50  
51  	public static void main(String[] args) {
52  		SpringApplication.run(Application.class, args);
53  	}
54  	
55  	@Bean
56  	@DependsOn("dataSourceInitializer")
57  	// @DependsOn only works if it is on a @Bean, so we can't use an @Import here
58  	protected AuthenticationManagerConfiguration authenticationManagerConfiguration() {
59  		return new AuthenticationManagerConfiguration();
60  	}
61  
62  	@RequestMapping("/")
63  	public String home() {
64  		return "Hello World";
65  	}
66  
67  	@Configuration
68  	protected static class ResourceServer extends WebSecurityConfigurerAdapter {
69  
70  		@Autowired
71  		@Qualifier("resourceFilter")
72  		private Filter resourceFilter;
73  
74  		@Bean
75  		public FilterRegistrationBean resourceFilterRegistration() {
76  			FilterRegistrationBean bean = new FilterRegistrationBean();
77  			bean.setFilter(resourceFilter);
78  			bean.setEnabled(false);
79  			return bean;
80  		}
81  
82  		@Override
83  		protected void configure(HttpSecurity http) throws Exception {
84  			// @formatter:off	
85  			http.addFilterBefore(resourceFilter, AbstractPreAuthenticatedProcessingFilter.class)
86  				.requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/oauth/**")))
87  				.authorizeRequests().anyRequest().authenticated().expressionHandler(new OAuth2WebSecurityExpressionHandler())
88  			.and()
89  				.anonymous().disable()
90  				.csrf().disable()
91  				.exceptionHandling()
92  					.authenticationEntryPoint(new OAuth2AuthenticationEntryPoint())
93  					.accessDeniedHandler(new OAuth2AccessDeniedHandler());
94  			// @formatter:on
95  		}
96  
97  	}
98  
99  	@Configuration
100 	protected static class OAuth2Config {
101 
102 		@Autowired
103 		private DataSource dataSource;
104 
105 		@Bean
106 		public JdbcClientDetailsService clientDetailsService() {
107 			return new JdbcClientDetailsService(dataSource);
108 		}
109 
110 		@Bean
111 		public JdbcTokenStore tokenStore() {
112 			return new JdbcTokenStore(dataSource);
113 		}
114 
115 		@Bean
116 		protected AuthorizationCodeServices authorizationCodeServices() {
117 			return new JdbcAuthorizationCodeServices(dataSource);
118 		}
119 
120 		@Bean
121 		public DefaultTokenServices tokenServices() {
122 			DefaultTokenServices services = new DefaultTokenServices();
123 			services.setClientDetailsService(clientDetailsService());
124 			services.setSupportRefreshToken(true);
125 			services.setTokenStore(tokenStore());
126 			return services;
127 		}
128 
129 		@Bean
130 		public WhitelabelErrorEndpoint oauth2ErrorEndpoint() {
131 			return new WhitelabelErrorEndpoint();
132 		}
133 
134 		@Bean
135 		public WhitelabelApprovalEndpoint oauth2ApprovalEndpoint() {
136 			return new WhitelabelApprovalEndpoint();
137 		}
138 
139 	}
140 
141 	@Configuration
142 	@Order(Ordered.HIGHEST_PRECEDENCE)
143 	protected static class TokenEndpointSecurity extends WebSecurityConfigurerAdapter {
144 
145 		@Autowired
146 		private ClientDetailsService clientDetailsService;
147 
148 		@Override
149 		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
150 			auth.userDetailsService(clientDetailsUserService());
151 		}
152 
153 		@Bean
154 		protected UserDetailsService clientDetailsUserService() {
155 			return new ClientDetailsUserDetailsService(clientDetailsService);
156 		}
157 
158 		@Override
159 		protected void configure(HttpSecurity http) throws Exception {
160 			// @formatter:off
161 			http.anonymous().disable()
162 				.antMatcher("/oauth/token")
163 				.authorizeRequests().anyRequest().authenticated()
164 			.and()
165 				.httpBasic().authenticationEntryPoint(authenticationEntryPoint())
166 			.and()
167 				.csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable()
168 				.exceptionHandling().accessDeniedHandler(accessDeniedHandler())
169 			.and()
170 				.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
171 			// @formatter:on
172 		}
173 
174 		@Bean
175 		protected AccessDeniedHandler accessDeniedHandler() {
176 			return new OAuth2AccessDeniedHandler();
177 		}
178 
179 		@Bean
180 		protected AuthenticationEntryPoint authenticationEntryPoint() {
181 			OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
182 			entryPoint.setTypeName("Basic");
183 			entryPoint.setRealmName("oauth2/client");
184 			return entryPoint;
185 		}
186 
187 	}
188 
189 }
190 
191 @Order(Ordered.LOWEST_PRECEDENCE - 8)
192 class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {
193 
194 	@Autowired
195 	private DataSource dataSource;
196 
197 	@Autowired
198 	private SecurityProperties security;
199 
200 	@Override
201 	public void init(AuthenticationManagerBuilder auth) throws Exception {
202 		User user = security.getUser();
203 		// @formatter:off
204 		auth.jdbcAuthentication().dataSource(dataSource)
205 			.withUser(user.getName())
206 			.password(user.getPassword())
207 			.roles(user.getRole().toArray(new String[0]));
208 		// @formatter:on
209 	}
210 }