Commit 118d7260 authored by Aleksandr Sharaban's avatar Aleksandr Sharaban Committed by Matija Obreza
Browse files

Migrated spring-security.xml and spring-security-oauth.xml to Java Config

parent 41fdf29c
......@@ -92,7 +92,7 @@
<aspectj.version>1.7.2</aspectj.version>
<mysql.version>5.1.31</mysql.version>
<hazelcast.version>3.4</hazelcast.version>
<hazelcast.version>3.6</hazelcast.version>
<oval.version>1.81</oval.version>
<jackson.version>2.2.1</jackson.version>
......
package org.genesys2.server.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Autowired
@Qualifier("permissionEvaluator")
private PermissionEvaluator permissionEvaluator;
@Bean
public MethodSecurityExpressionHandler expressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(permissionEvaluator);
return expressionHandler;
}
}
package org.genesys2.server.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import javax.inject.Named;
@Configuration
@Order(1)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Named("authUserDetailsService")
private UserDetailsService userDetailsService;
@Autowired
@Qualifier("webExpressionHandler")
private DefaultWebSecurityExpressionHandler expressionHandler;
@Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
//Do not filter static resources and other stuff
web.ignoring()
.antMatchers("/html/**", "/webapi/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//Closed page and Authentication filter
http
.authorizeRequests()
.expressionHandler(expressionHandler)
// .antMatchers("/data/**").authenticated()
.antMatchers("/admin/**").access("hasRole('ADMINISTRATOR')")
.antMatchers("/1/admin/**").access("hasRole('ADMINISTRATOR')")
.antMatchers("/profile**").authenticated()
.antMatchers("/oauth/authorize").authenticated()
//Override default login and logout pages
.and()
.formLogin().loginPage("/login")
.failureUrl("/login?error=1")
.loginProcessingUrl("/login-attempt")
.defaultSuccessUrl("/", false)
.and()
// session-fixation-protection
.sessionManagement()
.sessionFixation().migrateSession()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.exceptionHandling()
.accessDeniedPage("/access-denied")
//Enable CSRF protection
.and()
.csrf();
}
}
package org.genesys2.server.config;
import org.genesys2.server.service.OAuth2ClientDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter;
import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.Filter;
@Configuration
@Order(2)
public class SecurityOauthConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("clientDetails")
private OAuth2ClientDetailsService clientDetails;
@Autowired
@Qualifier("tokenStore")
private TokenStore tokenStore;
@Autowired
@Qualifier("passwordEncoder")
private PasswordEncoder passwordEncoder;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(clientDetailsUserService())
.passwordEncoder(passwordEncoder);
}
@Bean(name="clientAuthenticationManager")
@Override
public AuthenticationManager authenticationManager() throws Exception {
return authenticationManagerBean();
}
@Bean
public AccessDeniedHandler oauthAccessDeniedHandler() {
return new OAuth2AccessDeniedHandler();
}
@Bean(name = "clientDetailsUserService")
public UserDetailsService clientDetailsUserService() {
return new ClientDetailsUserDetailsService(clientDetails);
}
@Bean(name = "tokenServices")
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
tokenServices.setSupportRefreshToken(true);
tokenServices.setClientDetailsService(clientDetails);
return tokenServices;
}
@Bean(name = "resourceServerFilter")
public OAuth2AuthenticationProcessingFilter qOAuth2AuthenticationProcessingFilter() {
OAuth2AuthenticationProcessingFilter processingFilter = new OAuth2AuthenticationProcessingFilter();
processingFilter.setAuthenticationManager(this.auth2AM());
return processingFilter;
}
@Bean(name = "oauthExpressionHandler")
public OAuth2MethodSecurityExpressionHandler oauthExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
@Bean(name = "oauthWebExpressionHandler")
public OAuth2WebSecurityExpressionHandler oauthWebExpressionHandler() {
return new OAuth2WebSecurityExpressionHandler();
}
@Bean(name = "oauthAuthenticationEntryPoint")
public OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
authenticationEntryPoint.setRealmName("genesys2");
return authenticationEntryPoint;
}
@Bean(name = "clientAuthenticationEntryPoint")
public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
authenticationEntryPoint.setRealmName("genesys2/client");
authenticationEntryPoint.setTypeName("Basic");
return authenticationEntryPoint;
}
@Bean
public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception {
ClientCredentialsTokenEndpointFilter endpointFilter = new ClientCredentialsTokenEndpointFilter();
endpointFilter.setAuthenticationManager(authenticationManager());
return endpointFilter;
}
private OAuth2AuthenticationManager auth2AM() {
OAuth2AuthenticationManager oAuth2AuthenticationManager = new OAuth2AuthenticationManager();
oAuth2AuthenticationManager.setResourceId("crophub_oauth_server");
oAuth2AuthenticationManager.setTokenServices(tokenServices());
return oAuth2AuthenticationManager;
}
@Configuration
@Order(3)
public static class OauthTokenConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("clientAuthenticationEntryPoint")
private OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint;
@Autowired
private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter;
@Autowired
private AccessDeniedHandler oauthAccessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(clientAuthenticationEntryPoint)
//include this only if you need to authenticate clients via request parameters
.and()
.addFilterAfter(clientCredentialsTokenEndpointFilter,
BasicAuthenticationFilter.class)
.exceptionHandling()
.accessDeniedHandler(oauthAccessDeniedHandler)
.and()
.csrf().disable();
}
}
//The OAuth2 protected resources are separated out into their own block so we can deal with
//authorization and error handling separately. This isn't mandatory, but it makes it easier
//to control the behaviour.
@Configuration
@Order(4)
public static class OauthUsersClientsConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("oauthWebExpressionHandler")
private OAuth2WebSecurityExpressionHandler oauthWebExpressionHandler;
@Autowired
private AccessDeniedHandler oauthAccessDeniedHandler;
@Autowired
private OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint;
@Autowired
@Qualifier("resourceServerFilter")
private Filter resourceServerFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.expressionHandler(oauthWebExpressionHandler)
.regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*")
.access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or " +
"#oauth2.isClient()) and #oauth2.hasScope('write')")
.regexMatchers(HttpMethod.GET, "/oauth/users/.*")
.access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or " +
"#oauth2.isClient()) and #oauth2.hasScope('read')")
.regexMatchers(HttpMethod.GET, "/oauth/clients/.*")
.access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and " +
"#oauth2.hasScope('read')")
.antMatchers("/**").denyAll()
.and()
.addFilterBefore(resourceServerFilter,
AbstractPreAuthenticatedProcessingFilter.class)
.exceptionHandling()
.accessDeniedHandler(oauthAccessDeniedHandler)
.authenticationEntryPoint(oauthAuthenticationEntryPoint);
}
}
@Configuration
@Order(5)
public static class OauthApiConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("oauthWebExpressionHandler")
private OAuth2WebSecurityExpressionHandler oauthWebExpressionHandler;
@Autowired
private AccessDeniedHandler oauthAccessDeniedHandler;
@Autowired
private OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint;
@Autowired
@Qualifier("resourceServerFilter")
private Filter resourceServerFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.expressionHandler(oauthWebExpressionHandler)
.regexMatchers("/api/v0/.*").authenticated()
.antMatchers("/**").denyAll()
.and()
.httpBasic()
.authenticationEntryPoint(oauthAuthenticationEntryPoint)
.and()
.addFilterBefore(resourceServerFilter,
AbstractPreAuthenticatedProcessingFilter.class)
.exceptionHandling()
.accessDeniedHandler(oauthAccessDeniedHandler)
.authenticationEntryPoint(oauthAuthenticationEntryPoint)
.and()
.csrf().disable();
}
}
}
......@@ -18,18 +18,21 @@ package org.genesys2.spring.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.config.MethodSecurityConfig;
import org.genesys2.server.config.SecurityConfig;
import org.genesys2.server.config.SecurityOauthConfig;
import org.genesys2.spring.DefaultRolesPrefixPostProcessor;
import org.genesys2.transifex.client.TransifexService;
import org.genesys2.transifex.client.TransifexServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource({ "classpath:/spring/spring-security.xml" })
@Import({ SpringProperties.class, SpringCommonConfig.class, SpringAclConfig.class, SpringSchedulerConfig.class, SpringDataBaseConfig.class,
SpringMailConfig.class, SpringSecurityOauthConfig.class, SpringCacheConfig.class, ElasticsearchConfig.class, FileRepositoryConfig.class })
SpringMailConfig.class, SpringCacheConfig.class, ElasticsearchConfig.class, FileRepositoryConfig.class,
SecurityConfig.class, MethodSecurityConfig.class, SecurityOauthConfig.class, SecurityOauthConfig.OauthTokenConfig.class,
SecurityOauthConfig.OauthUsersClientsConfig.class, SecurityOauthConfig.OauthApiConfig.class})
public class ApplicationConfig {
public static final Log LOG = LogFactory.getLog(ApplicationConfig.class);
......
......@@ -25,6 +25,7 @@ import com.hazelcast.core.IQueue;
import com.hazelcast.spring.cache.HazelcastCacheManager;
import com.hazelcast.web.WebFilter;
import com.hazelcast.web.spring.SpringAwareWebFilter;
import org.genesys2.server.security.lockout.AccountLockoutManager.AttemptStatistics;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
......@@ -84,7 +85,7 @@ public class SpringCacheConfig {
@Bean
public WebFilter hazelcastWebFilter() {
return new WebFilter(filterProps());
return new SpringAwareWebFilter(filterProps());
}
private Properties filterProps() {
......
/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed 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 org.genesys2.spring.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource("classpath:/spring/spring-security-oauth.xml")
public class SpringSecurityOauthConfig {
}
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2014 Global Crop Diversity Trust
Licensed 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!-- <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean> -->
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<sec:authentication-manager id="clientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService">
<!-- <sec:password-encoder ref="passwordEncoder" /> -->
</sec:authentication-provider>
</sec:authentication-manager>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code authorization-code-services-ref="verificationCodeService" />
<oauth:refresh-token />
<oauth:password disabled="false" authentication-manager-ref="authenticationManager" />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="crophub_oauth_server" token-services-ref="tokenServices" />
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<sec:http pattern="/oauth/token" authentication-manager-ref="clientAuthenticationManager" create-session="stateless" xmlns="http://www.springframework.org/schema/security">
<sec:intercept-url pattern="/oauth/token" access="isAuthenticated()" />
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
<sec:csrf disabled="true" />
</sec:http>
<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling
separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<sec:http pattern="/oauth/(users|clients)/.*" authentication-manager-ref="clientAuthenticationManager" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="true" xmlns="http://www.springframework.org/schema/security">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/oauth/users/([^/].*?)/tokens/.*" access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')" method="DELETE" />
<sec:intercept-url pattern="/oauth/users/.*" access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')" method="GET" />
<sec:intercept-url pattern="/oauth/clients/.*" access="#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')" method="GET" />
<sec:intercept-url pattern="/**" access="denyAll()" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
<sec:expression-handler ref="oauthWebExpressionHandler" />
</sec:http>
<sec:http pattern="/api/v0/.*" authentication-manager-ref="clientAuthenticationManager" request-matcher="regex" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="true"
xmlns="http://www.springframework.org/schema/security">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/api/v0/.*" access="isAuthenticated()" />
<sec:intercept-url pattern="/**" access="denyAll()" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:http-basic entry-point-ref="oauthAuthenticationEntryPoint" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
<sec:expression-handler ref="oauthWebExpressionHandler" />
<sec:csrf disabled="true" />
</sec:http>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="genesys2" />
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="genesys2/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>