| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>AuthenticatedService.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">jUDDI Core Services</a> > <a href="index.source.html" class="el_package">org.apache.juddi.api.impl</a> > <span class="el_source">AuthenticatedService.java</span></div><h1>AuthenticatedService.java</h1><pre class="source lang-java linenums">/* |
| * Copyright 2001-2008 The Apache Software Foundation. |
| * |
| * 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.apache.juddi.api.impl; |
| |
| import java.util.Date; |
| import javax.annotation.Resource; |
| |
| import javax.persistence.EntityManager; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.xml.datatype.DatatypeConfigurationException; |
| import javax.xml.datatype.DatatypeFactory; |
| import javax.xml.ws.WebServiceContext; |
| import javax.xml.ws.handler.MessageContext; |
| |
| import org.apache.commons.configuration.ConfigurationException; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.juddi.config.AppConfig; |
| import org.apache.juddi.config.Property; |
| import org.apache.juddi.model.UddiEntityPublisher; |
| import org.apache.juddi.v3.auth.Authenticator; |
| import org.apache.juddi.v3.auth.AuthenticatorFactory; |
| import org.apache.juddi.v3.error.AuthTokenRequiredException; |
| import org.apache.juddi.v3.error.AuthTokenExpiredException; |
| import org.apache.juddi.v3.error.ErrorMessage; |
| import org.uddi.v3_service.DispositionReportFaultMessage; |
| |
| /** |
| * Although this class is abstract, it provides token validation |
| * |
| * @author <a href="mailto:jfaath@apache.org">Jeff Faath</a> |
| * |
| * @author <a href="mailto:alexoree@apache.org">Alex O'Ree</a> - modified to |
| * include token expiration validation |
| */ |
| public abstract class AuthenticatedService { |
| |
| /** |
| * @return the node |
| */ |
| public String getNode() { |
| <span class="fc" id="L56"> return node;</span> |
| } |
| |
| public static final String UTF8 = "UTF-8"; |
| public static final int AUTHTOKEN_ACTIVE = 1; |
| public static final int AUTHTOKEN_RETIRED = 0; |
| <span class="fc" id="L62"> static final Log logger = LogFactory.getLog(AuthenticatedService.class);</span> |
| /** |
| * the node id of this server instance, as loaded from the config file |
| */ |
| <span class="fc" id="L66"> private String node = "UNDEFINED_NODE_NAME";</span> |
| <span class="fc" id="L67"> protected String baseUrlSSL = "UNDEFINED";</span> |
| <span class="fc" id="L68"> protected String baseUrl = "UNDEFINED";</span> |
| <span class="fc" id="L69"> protected DatatypeFactory df = null;</span> |
| |
| <span class="fc" id="L71"> public AuthenticatedService() {</span> |
| try { |
| <span class="fc" id="L73"> node = AppConfig.getConfiguration().getString(Property.JUDDI_NODE_ID, "UNDEFINED_NODE_NAME");</span> |
| <span class="fc" id="L74"> node = node.trim();</span> |
| <span class="fc" id="L75"> baseUrlSSL = AppConfig.getConfiguration().getString(Property.JUDDI_BASE_URL_SECURE, Property.DEFAULT_BASE_URL_SECURE);</span> |
| <span class="fc" id="L76"> baseUrlSSL = baseUrlSSL.trim();</span> |
| <span class="nc" id="L77"> } catch (ConfigurationException ex) {</span> |
| <span class="nc" id="L78"> logger.fatal(null, ex);</span> |
| <span class="fc" id="L79"> }</span> |
| <span class="fc" id="L80"> init();</span> |
| <span class="fc" id="L81"> }</span> |
| |
| /** |
| * this method can be used to explicitly set a request context. this is useful |
| * in unit tests, embedded and in-vm scenarios only |
| * @param ctx |
| * @since 3.3.8 |
| */ |
| public void setContext(WebServiceContext ctx) { |
| <span class="nc" id="L90"> this.ctx = ctx;</span> |
| <span class="nc" id="L91"> }</span> |
| |
| private synchronized void init() { |
| try { |
| <span class="fc" id="L95"> df = DatatypeFactory.newInstance();</span> |
| <span class="nc" id="L96"> } catch (DatatypeConfigurationException ex) {</span> |
| <span class="nc" id="L97"> logger.fatal(null, ex);</span> |
| <span class="fc" id="L98"> }</span> |
| <span class="fc" id="L99"> }</span> |
| |
| @Resource |
| protected WebServiceContext ctx; |
| |
| public UddiEntityPublisher getEntityPublisher(EntityManager em, String authInfo) throws DispositionReportFaultMessage { |
| <span class="fc" id="L105"> boolean useAuthInfo = true;</span> |
| try { |
| <span class="fc" id="L107"> useAuthInfo = AppConfig.getConfiguration().getBoolean(Property.JUDDI_AUTHENTICATOR_USE_TOKEN, true);</span> |
| <span class="nc" id="L108"> } catch (ConfigurationException ex) {</span> |
| |
| <span class="fc" id="L110"> }</span> |
| <span class="pc bpc" id="L111" title="1 of 2 branches missed."> if (useAuthInfo) {</span> |
| |
| <span class="pc bpc" id="L113" title="1 of 4 branches missed."> if (authInfo == null || authInfo.length() == 0) {</span> |
| <span class="fc" id="L114"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthRequired"));</span> |
| } |
| |
| <span class="fc" id="L117"> org.apache.juddi.model.AuthToken modelAuthToken = em.find(org.apache.juddi.model.AuthToken.class, authInfo);</span> |
| <span class="pc bpc" id="L118" title="1 of 2 branches missed."> if (modelAuthToken == null) {</span> |
| <span class="nc" id="L119"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthInvalid"));</span> |
| } |
| |
| <span class="fc" id="L122"> int allowedMinutesOfInactivity = 0;</span> |
| try { |
| <span class="fc" id="L124"> allowedMinutesOfInactivity = AppConfig.getConfiguration().getInt(Property.JUDDI_AUTH_TOKEN_TIMEOUT, 0);</span> |
| <span class="nc" id="L125"> } catch (ConfigurationException ce) {</span> |
| <span class="nc" id="L126"> logger.error("Error reading property " + Property.JUDDI_AUTH_TOKEN_EXPIRATION + " from "</span> |
| + "the application's configuration. No automatic timeout token invalidation will occur. " |
| <span class="nc" id="L128"> + ce.getMessage(), ce);</span> |
| <span class="fc" id="L129"> }</span> |
| <span class="fc" id="L130"> int maxMinutesOfAge = 0;</span> |
| try { |
| <span class="fc" id="L132"> maxMinutesOfAge = AppConfig.getConfiguration().getInt(Property.JUDDI_AUTH_TOKEN_EXPIRATION, 0);</span> |
| <span class="nc" id="L133"> } catch (ConfigurationException ce) {</span> |
| <span class="nc" id="L134"> logger.error("Error reading property " + Property.JUDDI_AUTH_TOKEN_EXPIRATION + " from "</span> |
| + "the application's configuration. No automatic timeout token invalidation will occur. " |
| <span class="nc" id="L136"> + ce.getMessage(), ce);</span> |
| <span class="fc" id="L137"> }</span> |
| <span class="fc" id="L138"> Date now = new Date();</span> |
| // 0 or negative means token does not expire |
| <span class="pc bpc" id="L140" title="1 of 2 branches missed."> if (allowedMinutesOfInactivity > 0) {</span> |
| // expire tokens after # minutes of inactivity |
| // compare the time in milli-seconds |
| <span class="pc bpc" id="L143" title="1 of 2 branches missed."> if (now.getTime() > modelAuthToken.getLastUsed().getTime() + allowedMinutesOfInactivity * 60000l) {</span> |
| <span class="nc" id="L144"> logger.info("AUDIT: FAILTURE Token " + modelAuthToken.getAuthToken() + " expired due to inactivity " + getRequestorsIPAddress());</span> |
| <span class="nc" id="L145"> modelAuthToken.setTokenState(AUTHTOKEN_RETIRED);</span> |
| } |
| } |
| <span class="pc bpc" id="L148" title="1 of 2 branches missed."> if (maxMinutesOfAge > 0) {</span> |
| // expire tokens when max age is reached |
| // compare the time in milli-seconds |
| <span class="pc bpc" id="L151" title="1 of 2 branches missed."> if (now.getTime() > modelAuthToken.getCreated().getTime() + maxMinutesOfAge * 60000l) {</span> |
| |
| <span class="nc" id="L153"> logger.info("AUDIT: FAILURE - Token " + modelAuthToken.getAuthorizedName() + " expired due to old age " + getRequestorsIPAddress());</span> |
| <span class="nc" id="L154"> modelAuthToken.setTokenState(AUTHTOKEN_RETIRED);</span> |
| } |
| } |
| |
| <span class="pc bpc" id="L158" title="1 of 2 branches missed."> if (modelAuthToken.getTokenState() == AUTHTOKEN_RETIRED) {</span> |
| |
| <span class="nc" id="L160"> throw new AuthTokenExpiredException(new ErrorMessage("errors.auth.AuthTokenExpired"));</span> |
| } |
| <span class="fc bfc" id="L162" title="All 2 branches covered."> if (ctx != null) {</span> |
| try { |
| <span class="fc" id="L164"> boolean check = true;</span> |
| try { |
| <span class="fc" id="L166"> check = AppConfig.getConfiguration().getBoolean(Property.JUDDI_AUTH_TOKEN_ENFORCE_SAME_IP, true);</span> |
| <span class="nc" id="L167"> } catch (ConfigurationException ex) {</span> |
| <span class="nc" id="L168"> logger.warn("Error loading config property " + Property.JUDDI_AUTH_TOKEN_ENFORCE_SAME_IP</span> |
| + " Enforcing Same IP for Auth Tokens will be enabled by default", ex); |
| <span class="fc" id="L170"> }</span> |
| <span class="pc bpc" id="L171" title="1 of 2 branches missed."> if (check) {</span> |
| <span class="fc" id="L172"> MessageContext mc = ctx.getMessageContext();</span> |
| <span class="fc" id="L173"> HttpServletRequest req = null;</span> |
| <span class="pc bpc" id="L174" title="1 of 2 branches missed."> if (mc != null) {</span> |
| <span class="fc" id="L175"> req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);</span> |
| } |
| <span class="pc bpc" id="L177" title="1 of 2 branches missed."> if (req != null</span> |
| <span class="fc bfc" id="L178" title="All 2 branches covered."> && req.getRemoteAddr() != null</span> |
| <span class="fc bfc" id="L179" title="All 2 branches covered."> && modelAuthToken.getIPAddress() != null</span> |
| <span class="fc bfc" id="L180" title="All 2 branches covered."> && !modelAuthToken.getIPAddress().equalsIgnoreCase(req.getRemoteAddr())) {</span> |
| <span class="fc" id="L181"> modelAuthToken.setTokenState(AUTHTOKEN_RETIRED);</span> |
| <span class="fc" id="L182"> logger.error("AUDIT FAILURE - Security Alert - Attempt to use issued auth token from a different IP address, user "</span> |
| <span class="fc" id="L183"> + modelAuthToken.getAuthorizedName() + ", issued IP " + modelAuthToken.getIPAddress()</span> |
| <span class="fc" id="L184"> + ", attempted use from " + req.getRemoteAddr() + ", forcing reauthentication.");</span> |
| <span class="fc" id="L185"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthInvalid"));</span> |
| //invalidate the token, someone's intercepted it or it was reused on another ip |
| } |
| } |
| <span class="fc" id="L189"> } catch (Exception ex) {</span> |
| <span class="pc bpc" id="L190" title="1 of 2 branches missed."> if (ex instanceof AuthTokenRequiredException) {</span> |
| <span class="fc" id="L191"> throw (AuthTokenRequiredException) ex;</span> |
| } |
| <span class="nc" id="L193"> logger.error("unexpected error caught looking up requestor's ip address", ex);</span> |
| <span class="fc" id="L194"> }</span> |
| |
| } |
| <span class="fc" id="L197"> Authenticator authenticator = AuthenticatorFactory.getAuthenticator();</span> |
| <span class="fc" id="L198"> UddiEntityPublisher entityPublisher = authenticator.identify(authInfo, modelAuthToken.getAuthorizedName(), ctx);</span> |
| |
| // Must make sure the returned publisher has all the necessary fields filled |
| <span class="pc bpc" id="L201" title="1 of 2 branches missed."> if (entityPublisher == null) {</span> |
| <span class="nc" id="L202"> logger.warn("AUDIT FAILURE - Auth token invalid, publisher does not exist " + getRequestorsIPAddress());</span> |
| <span class="nc" id="L203"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthInvalid"));</span> |
| } |
| <span class="pc bpc" id="L205" title="1 of 2 branches missed."> if (entityPublisher.getAuthorizedName() == null) {</span> |
| <span class="nc" id="L206"> logger.warn("AUDIT FAILURE - Auth token invalid, username does exist" + getRequestorsIPAddress());</span> |
| <span class="nc" id="L207"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthInvalid"));</span> |
| } |
| // Auth token is being used. Adjust appropriate values so that it's internal 'expiration clock' is reset. |
| <span class="fc" id="L210"> modelAuthToken.setLastUsed(new Date());</span> |
| <span class="fc" id="L211"> modelAuthToken.setNumberOfUses(modelAuthToken.getNumberOfUses() + 1);</span> |
| <span class="fc" id="L212"> return entityPublisher;</span> |
| } else { |
| //use non-token based authentication |
| <span class="nc" id="L215"> Authenticator authenticator = AuthenticatorFactory.getAuthenticator();</span> |
| <span class="nc" id="L216"> UddiEntityPublisher entityPublisher = authenticator.identify(null, null, ctx);</span> |
| // Must make sure the returned publisher has all the necessary fields filled |
| <span class="nc bnc" id="L218" title="All 2 branches missed."> if (entityPublisher == null) {</span> |
| <span class="nc" id="L219"> logger.warn("AUDIT FAILURE - Auth token invalid, publisher does not exist " + getRequestorsIPAddress());</span> |
| <span class="nc" id="L220"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthInvalid"));</span> |
| } |
| <span class="nc bnc" id="L222" title="All 2 branches missed."> if (entityPublisher.getAuthorizedName() == null) {</span> |
| <span class="nc" id="L223"> logger.warn("AUDIT FAILURE - Auth token invalid, username does exist" + getRequestorsIPAddress());</span> |
| <span class="nc" id="L224"> throw new AuthTokenRequiredException(new ErrorMessage("errors.auth.AuthInvalid"));</span> |
| } |
| <span class="nc" id="L226"> return entityPublisher;</span> |
| |
| } |
| |
| } |
| |
| /** |
| * Attempts to get the requestor's ip address from the servlet context, |
| * defaults to null it it can't be retrieved |
| * |
| * @return requestor's ip address or null if it's not available |
| */ |
| public String getRequestorsIPAddress() { |
| try { |
| <span class="fc" id="L240"> MessageContext mc = ctx.getMessageContext();</span> |
| <span class="fc" id="L241"> HttpServletRequest req = null;</span> |
| <span class="pc bpc" id="L242" title="1 of 2 branches missed."> if (mc != null) {</span> |
| <span class="fc" id="L243"> req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);</span> |
| } |
| <span class="pc bpc" id="L245" title="1 of 2 branches missed."> if (req != null) {</span> |
| <span class="fc" id="L246"> return req.getRemoteAddr();</span> |
| } |
| <span class="fc" id="L248"> } catch (Exception ex) {</span> |
| <span class="fc" id="L249"> logger.debug("Error caught looking up the requestor's ip address", ex);</span> |
| <span class="nc" id="L250"> }</span> |
| <span class="fc" id="L251"> return null;</span> |
| } |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.7.9.201702052155</span></div></body></html> |