From ae4c8118af242904638a2e039964ec8d44e91289 Mon Sep 17 00:00:00 2001 From: GIP RECIA - Julien Gribonvald Date: Fri, 6 Mar 2020 18:26:26 +0100 Subject: [PATCH] feat: add OIDC protection to rest API with spring-boot help --- pom.xml | 86 +++++++++++-- .../ChangeEtablissementApplication.java | 20 +++ .../changeetab/ServletInitializer.java | 14 +++ .../changeetab/dao/impl/LdapStructureDao.java | 9 +- .../changeetab/dao/impl/LdapUserDao.java | 7 +- .../changeetab/dao/impl/MockStructureDao.java | 4 +- .../changeetab/dao/impl/MockUserDao.java | 4 +- .../security/SecurityConfiguration.java | 119 ++++++++++++++++++ .../changeetab/service/ISecurityChecker.java | 7 -- .../service/impl/BasicUserService.java | 7 +- .../service/impl/CachingStructureService.java | 22 ++-- .../service/impl/MockedSecurityChecker.java | 13 -- .../service/impl/SecurityChecker.java | 66 ---------- .../controller/ChangeStructureController.java | 20 ++- .../web/controller/WebMvcConfiguration.java | 16 +++ .../rest/ChangeStructureRestV2Controller.java | 14 +-- .../web/rest/StructureRestV1Controller.java | 7 +- .../web/rest/StructureRestV2Controller.java | 12 +- .../context/applicationContext.xml | 15 +-- .../context/jmxContext.xml | 0 .../resources/context/portlet/change-etab.xml | 38 ++++++ .../WEB-INF/context/portlet/change-etab.xml | 67 ---------- .../webapp/WEB-INF/context/spring-servlet.xml | 25 ---- src/main/webapp/WEB-INF/portlet.xml | 6 +- src/main/webapp/WEB-INF/web.xml | 25 +--- .../impl/CachingStructureServiceTest.java | 1 - .../rest/StructureRestV2ControllerTest.java | 30 ++--- src/test/resources/restApiContext.xml | 38 +++++- 28 files changed, 388 insertions(+), 304 deletions(-) create mode 100644 src/main/java/org/esco/portlet/changeetab/ChangeEtablissementApplication.java create mode 100644 src/main/java/org/esco/portlet/changeetab/ServletInitializer.java create mode 100644 src/main/java/org/esco/portlet/changeetab/security/SecurityConfiguration.java delete mode 100644 src/main/java/org/esco/portlet/changeetab/service/ISecurityChecker.java delete mode 100644 src/main/java/org/esco/portlet/changeetab/service/impl/MockedSecurityChecker.java delete mode 100644 src/main/java/org/esco/portlet/changeetab/service/impl/SecurityChecker.java create mode 100644 src/main/java/org/esco/portlet/changeetab/web/controller/WebMvcConfiguration.java rename src/main/{webapp/WEB-INF => resources}/context/applicationContext.xml (94%) rename src/main/{webapp/WEB-INF => resources}/context/jmxContext.xml (100%) create mode 100644 src/main/resources/context/portlet/change-etab.xml delete mode 100644 src/main/webapp/WEB-INF/context/portlet/change-etab.xml delete mode 100644 src/main/webapp/WEB-INF/context/spring-servlet.xml diff --git a/pom.xml b/pom.xml index 57e7c612..558ef9da 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ Change etablissement Portlet Change etablissement Portlet. - 2.2.0-SNAPSHOT + 3.0.0-SNAPSHOT 2012 @@ -69,6 +69,7 @@ 2.4.0 1.3.1 4.3.26.RELEASE + 1.5.22.RELEASE 2.3.2.RELEASE 1.7.25 1.2.3 @@ -206,6 +207,16 @@ + + org.jasig.portal + uPortal-soffit-renderer + ${uportal-libs.version} + + + org.jasypt + jasypt-spring31 + 1.9.3 + org.mockito mockito-core @@ -217,6 +228,16 @@ 1.0.9 test + + org.springframework.boot + spring-boot-starter-security + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + org.springframework spring-test @@ -234,24 +255,34 @@ org.springframework - spring-expression + spring-webmvc ${spring.version} - org.springframework.security - spring-security-web - 4.2.14.RELEASE + org.springframework + spring-webmvc-portlet + ${spring.version} org.springframework - spring-webmvc + spring-expression ${spring.version} org.springframework - spring-webmvc-portlet + spring-aop ${spring.version} + + org.springframework.security + spring-security-web + 4.2.14.RELEASE + + + org.springframework.security + spring-security-config + 4.2.14.RELEASE + org.springframework.ldap spring-ldap-core @@ -330,6 +361,10 @@ org.jasig.portal uPortal-spring + + org.jasig.portal + uPortal-soffit-renderer + org.mockito mockito-core @@ -345,6 +380,14 @@ spring-test test + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + org.springframework spring-context-support @@ -354,13 +397,29 @@ spring-web - org.springframework.security - spring-security-web + org.springframework + spring-webmvc org.springframework spring-webmvc-portlet + + org.springframework + spring-expression + + + org.springframework + spring-aop + + + org.springframework.security + spring-security-web + + + org.springframework.security + spring-security-config + org.springframework.ldap spring-ldap-core @@ -426,6 +485,15 @@ change-etablissement + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + org.esco.portlet.changeetab.ChangeEtablissementApplication + + + maven-release-plugin 2.5.3 diff --git a/src/main/java/org/esco/portlet/changeetab/ChangeEtablissementApplication.java b/src/main/java/org/esco/portlet/changeetab/ChangeEtablissementApplication.java new file mode 100644 index 00000000..03dc08db --- /dev/null +++ b/src/main/java/org/esco/portlet/changeetab/ChangeEtablissementApplication.java @@ -0,0 +1,20 @@ +package org.esco.portlet.changeetab; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ImportResource; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +@SpringBootApplication +@ImportResource(locations = {"classpath:context/*.xml"}) +public class ChangeEtablissementApplication { + + @Autowired + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer; + + public static void main(String[] args) { + SpringApplication.run(ChangeEtablissementApplication.class, args); + } + +} diff --git a/src/main/java/org/esco/portlet/changeetab/ServletInitializer.java b/src/main/java/org/esco/portlet/changeetab/ServletInitializer.java new file mode 100644 index 00000000..93dd6f07 --- /dev/null +++ b/src/main/java/org/esco/portlet/changeetab/ServletInitializer.java @@ -0,0 +1,14 @@ +package org.esco.portlet.changeetab; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; + +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(ChangeEtablissementApplication.class); + } + + +} diff --git a/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapStructureDao.java b/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapStructureDao.java index 2493dd02..f185ba9b 100644 --- a/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapStructureDao.java +++ b/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapStructureDao.java @@ -28,23 +28,20 @@ import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; - import org.esco.portlet.changeetab.dao.IStructureDao; import org.esco.portlet.changeetab.dao.bean.IStructureFormatter; import org.esco.portlet.changeetab.model.Structure; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.filter.AndFilter; import org.springframework.ldap.filter.EqualsFilter; import org.springframework.ldap.filter.HardcodedFilter; -import org.springframework.stereotype.Service; import org.springframework.util.Assert; /** * @author GIP RECIA 2013 - Maxime BOSSARD. * */ -@Service +//@Service @Data @Slf4j @NoArgsConstructor @@ -67,10 +64,10 @@ public class LdapStructureDao implements IStructureDao/*, InitializingBean*/{ @NonNull private Set classValueStructUAI; - @Autowired + //@Autowired private LdapTemplate ldapTemplate; - @Autowired(required = false) + //@Autowired(required = false) private List structureFormatters; /** Structure Ldap base. */ diff --git a/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapUserDao.java b/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapUserDao.java index 6d27e89a..8a4f89f7 100644 --- a/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapUserDao.java +++ b/src/main/java/org/esco/portlet/changeetab/dao/impl/LdapUserDao.java @@ -28,24 +28,21 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; - import org.esco.portlet.changeetab.dao.IUserDao; import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ldap.core.DistinguishedName; import org.springframework.ldap.core.LdapTemplate; -import org.springframework.stereotype.Service; import org.springframework.util.Assert; /** * @author GIP RECIA 2013 - Maxime BOSSARD. * */ -@Service +//@Service @Data @NoArgsConstructor public class LdapUserDao implements IUserDao, InitializingBean { @@ -56,7 +53,7 @@ public class LdapUserDao implements IUserDao, InitializingBean { @NonNull private String userIdTemplate = "%u"; - @Autowired + //@Autowired private LdapTemplate ldapTemplate; /** User base Ldap dn. */ diff --git a/src/main/java/org/esco/portlet/changeetab/dao/impl/MockStructureDao.java b/src/main/java/org/esco/portlet/changeetab/dao/impl/MockStructureDao.java index 6341aab6..e8db71d6 100644 --- a/src/main/java/org/esco/portlet/changeetab/dao/impl/MockStructureDao.java +++ b/src/main/java/org/esco/portlet/changeetab/dao/impl/MockStructureDao.java @@ -27,19 +27,17 @@ import java.util.Map; import lombok.extern.slf4j.Slf4j; - import org.apache.commons.collections.map.HashedMap; import org.esco.portlet.changeetab.dao.IStructureDao; import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; import org.springframework.beans.factory.InitializingBean; -import org.springframework.stereotype.Service; /** * @author GIP RECIA 2013 - Maxime BOSSARD. * */ -@Service +//@Service @Slf4j public class MockStructureDao implements IStructureDao, InitializingBean { diff --git a/src/main/java/org/esco/portlet/changeetab/dao/impl/MockUserDao.java b/src/main/java/org/esco/portlet/changeetab/dao/impl/MockUserDao.java index dee3330d..2c650ee7 100644 --- a/src/main/java/org/esco/portlet/changeetab/dao/impl/MockUserDao.java +++ b/src/main/java/org/esco/portlet/changeetab/dao/impl/MockUserDao.java @@ -29,20 +29,18 @@ import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; - import org.esco.portlet.changeetab.dao.IUserDao; import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; import org.springframework.beans.factory.InitializingBean; import org.springframework.ldap.core.DistinguishedName; -import org.springframework.stereotype.Service; import org.springframework.util.Assert; /** * @author GIP RECIA 2013 - Maxime BOSSARD. * */ -@Service +//@Service @Data @Slf4j @NoArgsConstructor diff --git a/src/main/java/org/esco/portlet/changeetab/security/SecurityConfiguration.java b/src/main/java/org/esco/portlet/changeetab/security/SecurityConfiguration.java new file mode 100644 index 00000000..3bee79c1 --- /dev/null +++ b/src/main/java/org/esco/portlet/changeetab/security/SecurityConfiguration.java @@ -0,0 +1,119 @@ +package org.esco.portlet.changeetab.security; + +import static org.apereo.portal.soffit.service.AbstractJwtService.DEFAULT_SIGNATURE_KEY; +import static org.apereo.portal.soffit.service.AbstractJwtService.SIGNATURE_KEY_PROPERTY; + +import java.util.Arrays; +import java.util.List; + +import lombok.extern.slf4j.Slf4j; +import org.apereo.portal.soffit.security.SoffitApiAuthenticationManager; +import org.apereo.portal.soffit.security.SoffitApiPreAuthenticatedProcessingFilter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.support.ErrorPageFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +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.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.NegatedRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.util.Assert; + +@EnableWebSecurity +@Slf4j +@ComponentScan(basePackages = "org.esco.portlet.changeetab.web.rest", lazyInit = true) +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Value("${authorizedIpRange}") + private String authorizedIpRange; + + @Value("${" + SIGNATURE_KEY_PROPERTY + ":" + DEFAULT_SIGNATURE_KEY + "}") + private String signatureKey; + + @Override + public void configure(WebSecurity web) throws Exception { + /* + * Since this module includes portlets, we only want to apply Spring Security to requests + * targeting our REST APIs. + */ + final RequestMatcher pathMatcher = new AntPathRequestMatcher("/rest/**"); + final RequestMatcher inverseMatcher = new NegatedRequestMatcher(pathMatcher); + web.ignoring().requestMatchers(inverseMatcher); + } + + + @Override + protected void configure(HttpSecurity http) throws Exception { + Assert.notNull(authorizedIpRange, "Property authorizedIpRange should be defined with an IP range"); + final List ips = Arrays.asList(authorizedIpRange.split(",")); + String hasIpRangeAccessExpresion = ""; + for (String ip: ips) { + hasIpRangeAccessExpresion += " or hasIpAddress('" + ip + "')"; + } + + log.debug("Constructing security with authorized ips : {}", authorizedIpRange); + + http + .addFilter(preAuthenticatedProcessingFilter()) + .authorizeRequests() + .antMatchers(HttpMethod.GET,"/rest/**").access("isAuthenticated()" + hasIpRangeAccessExpresion) + .antMatchers(HttpMethod.POST,"/rest/**").access("isAuthenticated()" + hasIpRangeAccessExpresion) + .antMatchers(HttpMethod.DELETE,"/rest/**").denyAll() + .antMatchers(HttpMethod.PUT,"/rest/**").denyAll() + .anyRequest().permitAll() + .and() + /* + * Session fixation protection is provided by uPortal. Since portlet tech requires + * sessionCookiePath=/, we will make the portal unusable if other modules are changing + * the sessionId as well. + */ + .sessionManagement() + .sessionFixation().none() + .and() + /* + * Portlet POST requests include (Spring-based) CSRF protection managed by uPortal. + * REST APIs are secured by OIDC Id tokens. + */ + .csrf() + .ignoringAntMatchers("/rest/**"); + } + + @Bean + public AuthenticationManager authenticationManager() { + return new SoffitApiAuthenticationManager(); + } + + @Bean + public AbstractPreAuthenticatedProcessingFilter preAuthenticatedProcessingFilter() { + log.debug("Initializing security with signature key: {}", signatureKey); + final AbstractPreAuthenticatedProcessingFilter rslt = new SoffitApiPreAuthenticatedProcessingFilter(signatureKey); + rslt.setAuthenticationManager(authenticationManager()); + return rslt; + } + + @Bean + public ErrorPageFilter errorPageFilter() { + return new ErrorPageFilter(); + } + + @Bean + public FilterRegistrationBean disableSpringBootErrorFilter() { + /* + * The ErrorPageFilter (Spring) makes extra calls to HttpServletResponse.flushBuffer(), + * and this behavior produces many warnings in the portal logs during portlet requests. + */ + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); + filterRegistrationBean.setFilter(errorPageFilter()); + filterRegistrationBean.setEnabled(false); + + return filterRegistrationBean; + } +} + diff --git a/src/main/java/org/esco/portlet/changeetab/service/ISecurityChecker.java b/src/main/java/org/esco/portlet/changeetab/service/ISecurityChecker.java deleted file mode 100644 index 53fd01dc..00000000 --- a/src/main/java/org/esco/portlet/changeetab/service/ISecurityChecker.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.esco.portlet.changeetab.service; - -import javax.servlet.http.HttpServletRequest; - -public interface ISecurityChecker { - boolean isSecureAccess(HttpServletRequest request); -} diff --git a/src/main/java/org/esco/portlet/changeetab/service/impl/BasicUserService.java b/src/main/java/org/esco/portlet/changeetab/service/impl/BasicUserService.java index 496bc128..56825301 100644 --- a/src/main/java/org/esco/portlet/changeetab/service/impl/BasicUserService.java +++ b/src/main/java/org/esco/portlet/changeetab/service/impl/BasicUserService.java @@ -21,24 +21,21 @@ import lombok.Data; import lombok.NoArgsConstructor; - import org.esco.portlet.changeetab.dao.IUserDao; import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.service.IUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; import org.springframework.util.Assert; /** * @author GIP RECIA 2013 - Maxime BOSSARD. * */ -@Service +//@Service @Data @NoArgsConstructor public class BasicUserService implements IUserService { - @Autowired + //@Autowired private IUserDao userDao; @Override diff --git a/src/main/java/org/esco/portlet/changeetab/service/impl/CachingStructureService.java b/src/main/java/org/esco/portlet/changeetab/service/impl/CachingStructureService.java index 745a7ded..21930a29 100644 --- a/src/main/java/org/esco/portlet/changeetab/service/impl/CachingStructureService.java +++ b/src/main/java/org/esco/portlet/changeetab/service/impl/CachingStructureService.java @@ -19,10 +19,8 @@ */ package org.esco.portlet.changeetab.service.impl; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -30,43 +28,39 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; - -import net.sf.ehcache.Ehcache; import org.esco.portlet.changeetab.dao.IStructureDao; import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; +import org.esco.portlet.changeetab.service.IStructureService; import org.esco.portlet.changeetab.service.IUniteAdministrativeImmatriculeService; import org.joda.time.Duration; import org.joda.time.Instant; import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.Cache; import org.springframework.cache.Cache.ValueWrapper; -import org.springframework.stereotype.Service; import org.springframework.util.Assert; /** * @author GIP RECIA 2013 - Maxime BOSSARD. * */ -@Service +//@Service @Slf4j -public class CachingStructureService implements IUniteAdministrativeImmatriculeService, InitializingBean { +public class CachingStructureService implements IStructureService, IUniteAdministrativeImmatriculeService, InitializingBean { - @Autowired + //@Autowired @Getter @Setter private IStructureDao structureDao; - @Autowired - @Qualifier("structuresCache") + //@Autowired + //@Qualifier("structuresCache") @Getter @Setter private Cache structureCache; - @Autowired - @Qualifier("etabsCodeIdCache") + //@Autowired + //@Qualifier("etabsCodeIdCache") @Getter @Setter private Cache etabsCodeIdCache; diff --git a/src/main/java/org/esco/portlet/changeetab/service/impl/MockedSecurityChecker.java b/src/main/java/org/esco/portlet/changeetab/service/impl/MockedSecurityChecker.java deleted file mode 100644 index caa29b9e..00000000 --- a/src/main/java/org/esco/portlet/changeetab/service/impl/MockedSecurityChecker.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.esco.portlet.changeetab.service.impl; - -import org.esco.portlet.changeetab.service.ISecurityChecker; - -import javax.servlet.http.HttpServletRequest; - -public class MockedSecurityChecker implements ISecurityChecker { - - @Override - public boolean isSecureAccess(HttpServletRequest request) { - return true; - } -} diff --git a/src/main/java/org/esco/portlet/changeetab/service/impl/SecurityChecker.java b/src/main/java/org/esco/portlet/changeetab/service/impl/SecurityChecker.java deleted file mode 100644 index 1673c6b6..00000000 --- a/src/main/java/org/esco/portlet/changeetab/service/impl/SecurityChecker.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (C) 2017 GIP RECIA http://www.recia.fr - * @Author (C) 2013 Maxime Bossard - * @Author (C) 2016 Julien Gribonvald - * - * 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.esco.portlet.changeetab.service.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; - -import org.esco.portlet.changeetab.service.ISecurityChecker; -import org.springframework.security.web.util.matcher.IpAddressMatcher; -import org.springframework.security.web.util.matcher.RequestMatcher; - -/** - * Created by jgribonvald on 14/06/17. - */ -public class SecurityChecker implements ISecurityChecker { - - private Set ips = new HashSet<>(); - - private List matchers = new ArrayList<>(); - private boolean initialized = false; - - public SecurityChecker() { - super(); - } - public SecurityChecker(Set ips) { - this.ips = ips; - } - - public void setIps(final String ips) { - String[] tmp = ips.replaceAll("\\s", "").split(","); - this.ips = new HashSet<>(Arrays.asList(tmp)); - } - - @Override - public boolean isSecureAccess(final HttpServletRequest request){ - if (matchers.isEmpty() || !initialized) { - for (String ip: ips) { - matchers.add(new IpAddressMatcher(ip)); - } - } - - for (RequestMatcher rm: matchers) { - if (rm.matches(request)) return true; - } - return false; - } -} diff --git a/src/main/java/org/esco/portlet/changeetab/web/controller/ChangeStructureController.java b/src/main/java/org/esco/portlet/changeetab/web/controller/ChangeStructureController.java index 887a7939..336faf24 100644 --- a/src/main/java/org/esco/portlet/changeetab/web/controller/ChangeStructureController.java +++ b/src/main/java/org/esco/portlet/changeetab/web/controller/ChangeStructureController.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; +import javax.annotation.PostConstruct; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.RenderRequest; @@ -32,7 +33,6 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; - import org.apache.commons.collections.CollectionUtils; import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; @@ -42,7 +42,7 @@ import org.esco.portlet.changeetab.web.ChangeStructCommand; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.PropertyResolver; import org.springframework.stereotype.Controller; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -80,17 +80,20 @@ public class ChangeStructureController implements InitializingBean { private static final String DEFAULT_STRUCT_LOGO_KEY = "defaultStructLogo"; - @Value("${redirectAfterChange:false}") + @Autowired + private PropertyResolver propertyResolver; + + //@Value("${redirectAfterChange:false}") @Getter @Setter private boolean redirectAfterChange = false; - @Value("${logoutUrlRedirect:null}") + //@Value("${logoutUrlRedirect:null}") @Getter @Setter private String logoutUrlRedirect; - @Value("${ldap.read.attribute.structureLogo:null}") + //@Value("${ldap.read.attribute.structureLogo:null}") @Getter @Setter private String ldapLogoInOtherAttributeName; @@ -110,6 +113,13 @@ public class ChangeStructureController implements InitializingBean { @Setter private IUserService userService; + @PostConstruct + public void init() { + this.redirectAfterChange = Boolean.parseBoolean(propertyResolver.getRequiredProperty("redirectAfterChange")); + this.logoutUrlRedirect = propertyResolver.getProperty("logoutUrlRedirect", String.class, null); + this.ldapLogoInOtherAttributeName = propertyResolver.getProperty("ldap.read.attribute.structureLogo", String.class, null); + } + @ActionMapping(params = "action=changeStruct") public void newChangeStruct(@ModelAttribute("command") final ChangeStructCommand changeStructCommand, final ActionRequest request, final ActionResponse response) throws Exception { diff --git a/src/main/java/org/esco/portlet/changeetab/web/controller/WebMvcConfiguration.java b/src/main/java/org/esco/portlet/changeetab/web/controller/WebMvcConfiguration.java new file mode 100644 index 00000000..8fcc67fe --- /dev/null +++ b/src/main/java/org/esco/portlet/changeetab/web/controller/WebMvcConfiguration.java @@ -0,0 +1,16 @@ +package org.esco.portlet.changeetab.web.controller; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class WebMvcConfiguration extends WebMvcConfigurerAdapter { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/**").addResourceLocations("/"); + } +} diff --git a/src/main/java/org/esco/portlet/changeetab/web/rest/ChangeStructureRestV2Controller.java b/src/main/java/org/esco/portlet/changeetab/web/rest/ChangeStructureRestV2Controller.java index 680b235c..8f8aa953 100644 --- a/src/main/java/org/esco/portlet/changeetab/web/rest/ChangeStructureRestV2Controller.java +++ b/src/main/java/org/esco/portlet/changeetab/web/rest/ChangeStructureRestV2Controller.java @@ -19,31 +19,26 @@ import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import org.esco.portlet.changeetab.service.ISecurityChecker; import org.esco.portlet.changeetab.service.IStructureService; -import org.esco.portlet.changeetab.service.impl.SecurityChecker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; /** * Created by jgribonvald on 27/03/17. */ @Slf4j -@Controller -@RequestMapping(value = "/v2/change") +@RestController +@RequestMapping(value = "/rest/v2/change") public class ChangeStructureRestV2Controller { @Autowired private IStructureService structureService; - @Autowired - private ISecurityChecker securityChecker; - /* * Return always Json data (Accept Http Header value has no impact) * example of call : /CONTEXT-PATH/rest/v2/structures/refresh/SIREN @@ -51,9 +46,6 @@ public class ChangeStructureRestV2Controller { @RequestMapping(value = "/refresh/{id}", method = RequestMethod.POST, produces = "application/json") public ResponseEntity refresh(@PathVariable("id") final String id, HttpServletRequest request) { - if (!securityChecker.isSecureAccess(request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } if (id != null) { structureService.invalidateStructureById(id); return new ResponseEntity(HttpStatus.OK); diff --git a/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV1Controller.java b/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV1Controller.java index 5c7571de..ab88f9e6 100644 --- a/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV1Controller.java +++ b/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV1Controller.java @@ -24,24 +24,23 @@ import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; - import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; import org.esco.portlet.changeetab.service.IUniteAdministrativeImmatriculeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; /** * Created by jgribonvald on 27/07/16. */ @Slf4j -@Controller -@RequestMapping(value = "/v1/structures") +@RestController +@RequestMapping(value = "/rest/v1/structures") public class StructureRestV1Controller { @Autowired diff --git a/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV2Controller.java b/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV2Controller.java index 0008abaa..5c7372a1 100644 --- a/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV2Controller.java +++ b/src/main/java/org/esco/portlet/changeetab/web/rest/StructureRestV2Controller.java @@ -23,30 +23,27 @@ import lombok.extern.slf4j.Slf4j; import org.esco.portlet.changeetab.model.Structure; -import org.esco.portlet.changeetab.service.ISecurityChecker; import org.esco.portlet.changeetab.service.IStructureService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; /** * Created by jgribonvald on 27/03/17. */ @Slf4j -@Controller -@RequestMapping(value = "/v2/structures") +@RestController +@RequestMapping(value = "/rest/v2/structures") public class StructureRestV2Controller { @Autowired private IStructureService structureService; - @Autowired - private ISecurityChecker securityChecker; /* * Return always Json data (Accept Http Header value has no impact) * example of call : /CONTEXT-PATH/rest/v2/structures/struct/SIREN @@ -80,9 +77,6 @@ public ResponseEntity retrieveStructbInJson(@PathVariable(" @RequestMapping(value = "/refresh/{id}", method = RequestMethod.POST, produces = "application/json") public ResponseEntity refresh(@PathVariable("id") final String id, HttpServletRequest request) { - if (!securityChecker.isSecureAccess(request)) { - return new ResponseEntity(HttpStatus.FORBIDDEN); - } if (id != null) { structureService.invalidateStructureById(id); return new ResponseEntity(HttpStatus.OK); diff --git a/src/main/webapp/WEB-INF/context/applicationContext.xml b/src/main/resources/context/applicationContext.xml similarity index 94% rename from src/main/webapp/WEB-INF/context/applicationContext.xml rename to src/main/resources/context/applicationContext.xml index 033fe29e..2c2fda8a 100644 --- a/src/main/webapp/WEB-INF/context/applicationContext.xml +++ b/src/main/resources/context/applicationContext.xml @@ -1,8 +1,11 @@ + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> + + @@ -13,7 +16,7 @@ - + @@ -96,10 +99,6 @@ - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/context/portlet/change-etab.xml b/src/main/webapp/WEB-INF/context/portlet/change-etab.xml deleted file mode 100644 index a4a25c82..00000000 --- a/src/main/webapp/WEB-INF/context/portlet/change-etab.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - classpath:configuration.properties - - file:${portal.home}/global.properties - file:${portal.home}/change-etablissement-portlet.properties - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/context/spring-servlet.xml b/src/main/webapp/WEB-INF/context/spring-servlet.xml deleted file mode 100644 index f5089fe7..00000000 --- a/src/main/webapp/WEB-INF/context/spring-servlet.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/portlet.xml b/src/main/webapp/WEB-INF/portlet.xml index 13f36a26..3d9929ba 100644 --- a/src/main/webapp/WEB-INF/portlet.xml +++ b/src/main/webapp/WEB-INF/portlet.xml @@ -10,7 +10,7 @@ org.springframework.web.portlet.DispatcherPortlet contextConfigLocation - /WEB-INF/context/portlet/change-etab.xml + classpath:/context/portlet/change-etab.xml text/html @@ -40,7 +40,7 @@ org.springframework.web.portlet.DispatcherPortlet contextConfigLocation - /WEB-INF/context/portlet/change-etab.xml + classpath:/context/portlet/change-etab.xml text/html @@ -69,7 +69,7 @@ org.springframework.web.portlet.DispatcherPortlet contextConfigLocation - /WEB-INF/context/portlet/change-etab.xml + classpath:/context/portlet/change-etab.xml text/html diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index ff3d8b87..bc61f43d 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -4,12 +4,8 @@ metadata-complete="true" version="2.5"> Change Etablissement Portlet - Change Etablissement Portlet + Change Etablissement Portlet - JSR-286 (Portlet 2.0) portlet - - contextConfigLocation - /WEB-INF/context/applicationContext.xml,/WEB-INF/context/jmxContext.xml - webAppRootKey change-etab.root @@ -18,33 +14,20 @@ org.springframework.web.util.WebAppRootListener + - org.springframework.web.context.ContextLoaderListener + ch.qos.logback.classic.selector.servlet.ContextDetachingSCL - + ViewRendererServlet org.springframework.web.servlet.ViewRendererServlet 1 - - spring - org.springframework.web.servlet.DispatcherServlet - - contextConfigLocation - /WEB-INF/context/spring-servlet.xml - - 2 - ViewRendererServlet /WEB-INF/servlet/view - - spring - /rest/* - - \ No newline at end of file diff --git a/src/test/java/org/esco/portlet/changeetab/service/impl/CachingStructureServiceTest.java b/src/test/java/org/esco/portlet/changeetab/service/impl/CachingStructureServiceTest.java index 6e88a981..cb695f6c 100644 --- a/src/test/java/org/esco/portlet/changeetab/service/impl/CachingStructureServiceTest.java +++ b/src/test/java/org/esco/portlet/changeetab/service/impl/CachingStructureServiceTest.java @@ -33,7 +33,6 @@ import org.esco.portlet.changeetab.model.Structure; import org.esco.portlet.changeetab.model.UniteAdministrativeImmatriculee; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; diff --git a/src/test/java/org/esco/portlet/changeetab/web/rest/StructureRestV2ControllerTest.java b/src/test/java/org/esco/portlet/changeetab/web/rest/StructureRestV2ControllerTest.java index 1a3b1426..d60f1fea 100644 --- a/src/test/java/org/esco/portlet/changeetab/web/rest/StructureRestV2ControllerTest.java +++ b/src/test/java/org/esco/portlet/changeetab/web/rest/StructureRestV2ControllerTest.java @@ -2,21 +2,26 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.esco.portlet.changeetab.dao.IStructureDao; import org.esco.portlet.changeetab.model.Structure; -import org.esco.portlet.changeetab.service.ISecurityChecker; import org.esco.portlet.changeetab.service.IStructureService; import org.esco.portlet.changeetab.service.impl.CachingStructureService; -import org.hamcrest.Matcher; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Matchers; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; @@ -30,13 +35,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import javax.annotation.PostConstruct; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:cachingStructureServiceContext.xml", "classpath:restApiContext.xml"}) @@ -52,9 +50,6 @@ public class StructureRestV2ControllerTest { @Autowired private IStructureService structureService; - @Autowired - private ISecurityChecker securityChecker; - private MockMvc restContentMockMvc; private List structures = new ArrayList<>(); @@ -76,7 +71,6 @@ public void setup() { StructureRestV2Controller structureRestV2Controller = new StructureRestV2Controller(); ReflectionTestUtils.setField(structureRestV2Controller, "structureService", structureService); - ReflectionTestUtils.setField(structureRestV2Controller, "securityChecker", securityChecker); this.restContentMockMvc = MockMvcBuilders.standaloneSetup(structureRestV2Controller).build(); @@ -112,13 +106,13 @@ public Collection answer(InvocationOnMock invocation) throw @Test public void testRefresh() throws Exception { restContentMockMvc.perform( - post("/v2/structures/refresh/" + SIREN_1).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); + post("/rest/v2/structures/refresh/" + SIREN_1).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); } @Test public void testretrieveStructFromId() throws Exception { restContentMockMvc.perform( - get("/v2/structures/struct/" + SIREN_1).contentType(MediaType.APPLICATION_JSON)) + get("/rest/v2/structures/struct/" + SIREN_1).contentType(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultHandlers.print()) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) diff --git a/src/test/resources/restApiContext.xml b/src/test/resources/restApiContext.xml index 023a79bc..04a51b27 100644 --- a/src/test/resources/restApiContext.xml +++ b/src/test/resources/restApiContext.xml @@ -30,12 +30,46 @@ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd" > - - + + + + + classpath:configuration.properties + + file:${portal.home}/global.properties + file:${portal.home}/change-etablissement-portlet.properties + + + + + +