View Javadoc
1   package fr.ifremer.quadrige3.core.security.remote;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: Quadrige3 Client Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2017 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import fr.ifremer.quadrige3.core.config.QuadrigeCoreConfiguration;
27  import fr.ifremer.quadrige3.core.security.AuthenticationInfo;
28  import fr.ifremer.quadrige3.core.service.administration.user.UserService;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.http.HttpStatus;
32  import org.apache.http.auth.AuthScope;
33  import org.apache.http.auth.UsernamePasswordCredentials;
34  import org.apache.http.client.CredentialsProvider;
35  import org.apache.http.client.config.RequestConfig;
36  import org.apache.http.client.methods.CloseableHttpResponse;
37  import org.apache.http.client.methods.HttpGet;
38  import org.apache.http.impl.client.BasicCredentialsProvider;
39  import org.apache.http.impl.client.CloseableHttpClient;
40  import org.apache.http.impl.client.HttpClients;
41  import org.apache.http.util.EntityUtils;
42  import org.nuiton.i18n.I18n;
43  import org.springframework.stereotype.Service;
44  
45  import javax.annotation.Resource;
46  import java.io.IOException;
47  import java.net.URISyntaxException;
48  import java.net.URL;
49  
50  import static org.nuiton.i18n.I18n.t;
51  
52  /**
53   * <p>AuthenticationRemoteServiceImpl class.</p>
54   *
55   */
56  @Service("authenticationRemoteService")
57  public class AuthenticationRemoteServiceImpl implements AuthenticationRemoteService {
58  
59      private static final Log log = LogFactory.getLog(AuthenticationRemoteServiceImpl.class);
60  
61      @Resource(name = "userService")
62      protected UserService userService;
63      
64      @Resource
65      protected QuadrigeCoreConfiguration config;
66      
67      /** {@inheritDoc} */
68      @Override
69      public boolean canAuthenticate(AuthenticationInfo authenticationInfo) throws AuthenticationRemoteException {
70          boolean authenticated = false;
71          Boolean isExtranet = userService.isLoginExtranet(authenticationInfo.getLogin());
72  
73          try {
74              // if we known username origin (intranet or extranet), authenticate only once on the origin server 
75              if (isExtranet != null) {
76                  authenticated = authenticate(isExtranet, authenticationInfo);
77              }
78              
79              // if we don't known the username origin:
80              else {
81                  // try extranet first
82                  authenticated = authenticate(true/*extranet*/, authenticationInfo);
83                  
84                  // then try intranet
85                  if (!authenticated) {
86                      authenticated = authenticate(false/*intranet*/, authenticationInfo);
87                  }
88              }
89              
90          } catch (IOException e) {
91              log.error(I18n.t("quadrige3.error.authenticate.failed", e.getMessage()), e);
92          } catch (URISyntaxException e) {
93              throw new AuthenticationRemoteException(t("quadrige3.error.authenticate.failed", e, e.getMessage()));
94          }
95          return authenticated;
96      }
97      
98      /* -- Internal methods -- */   
99      
100     private boolean authenticate(boolean isExtranet, AuthenticationInfo authenticationInfo) throws IOException, URISyntaxException {
101         URL url = isExtranet ? config.getAuthenticationExtranetSiteUrl() : config.getAuthenticationIntranetSiteUrl();
102         Integer timeOut = isExtranet ? config.getAuthenticationExtranetSiteTimeout() : config.getAuthenticationIntranetSiteTimeout();
103         return authenticate(url, timeOut, authenticationInfo);
104     }
105     
106     private boolean authenticate(URL url, Integer timeOut, AuthenticationInfo authenticationInfo) throws IOException, URISyntaxException {
107         boolean success;
108         
109         if (log.isDebugEnabled()) {
110             log.debug(String.format("try to authenticate on [%s]", url));
111         }
112 
113         // build credentials information
114         CredentialsProvider credentialProvider = new BasicCredentialsProvider();
115         credentialProvider.setCredentials(new AuthScope(url.getHost(), url.getPort()),
116             new UsernamePasswordCredentials(authenticationInfo.getLogin(), authenticationInfo.getPassword()));
117 
118         // build request config for timeout 
119         RequestConfig config = RequestConfig.custom().setSocketTimeout(timeOut).setConnectTimeout(timeOut).build();
120 
121         // build http client (don't use HttpService because of use of different url and timeout)
122         try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultRequestConfig(config).setDefaultCredentialsProvider(credentialProvider).build()) {
123             HttpGet httpget = new HttpGet(url.toURI());
124             if (log.isDebugEnabled()) {
125                 log.debug("Executing request : " + httpget.getRequestLine());
126             }
127 
128             // execute request
129             try (CloseableHttpResponse response = httpclient.execute(httpget)) {
130                 if (log.isDebugEnabled()) {
131                     log.debug("Received response : " + response.getStatusLine());
132                 }
133                 int statusCode = response.getStatusLine().getStatusCode();
134                 success = statusCode == HttpStatus.SC_OK;
135                 EntityUtils.consume(response.getEntity());
136             }            
137         }
138         
139         return success;
140     }
141 }