【问题标题】:To send get request to Web API from Java Servlet从 Java Servlet 向 Web API 发送获取请求
【发布时间】:2016-03-18 06:53:24
【问题描述】:

常见问题

是否可以从 Java servlet 的 doGet 方法发送获取请求?我需要针对我的 Web API .NET 服务检查一些“票证”,所以我可以在 doGet 方法中从我的自定义 servlet 调用此服务吗?

public class IdentityProviderServlet extends HttpServlet {
...
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
...
// make request to Web API and save received user name to response
...
}

详情

我们有使用 TIBCO Spotfire 7.0 作为分析报告引擎的网络应用程序(.NET、MVC5)。 为了让我们的用户在网络应用程序中查看报告,我们使用 Spotfire WebPlayer(IIS 网络应用程序)和 JavaScript API。我们在 Web 应用程序中对用户进行身份验证,然后允许他们利用 JS API 获取对 WebPlayer 的请求。为了使用已经过身份验证的用户,我们在 WebPlayer 上实现了基于密钥票证的自定义身份验证,如 here 所述。因此,我们创建了由 Spotfire WebPlayer 加载并调用覆盖函数的 .NET 程序集。在这个函数中,我们调用 Web API 服务来验证用户并获取有效的 spotfire 用户名,然后我使用收到的用户名创建 IIdentity。 当新版本的 TIBCO Spotfire 7.5 发布时,我们发现他们 removed 支持自定义身份验证,因为他们 changed 架构现在他们支持“external authentication”。这种方法可以实现为 Java servlet,用于对用户进行身份验证,然后进行点火:

从 getUserPrincipal() 方法中获取用户名 javax.servlet.http.HttpServletRequest

所有这些都迫使我们用 Java 重写我们的逻辑。然而,我们不想改变我们身份验证的整体工作流程,我们想坚持已经工作的票务模式。我是 Java servlet 的新手,所以我的目标是实现基于 servlet 的相同身份验证。他们有example,其中servlet 类有方法doGetdoPost (link to zip with example)。我在这里假设我可以实现自己的 doGet 并向 Web API 发送请求以验证票证并取回用户名。

有意义吗?

【问题讨论】:

  • 只是一个简短的评论 - 在 7.6 中,新的 CustomAuthenticator API 被添加到 Spotfire 服务器,这可能更容易实现(尽管您的原始问题仍然相关)。

标签: java servlets asp.net-web-api2 servlet-filters spotfire


【解决方案1】:

最后我得到了这段代码。我实现了简单的过滤器而不是 servlet。

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import java.io.*;
import org.json.*;

public class Authenticator implements IAuthenticator {

    @Override
    public IIdentity doAuthentication(String pathToAuthIdentity) throws IOException {
        try {
            // Create an instance of HttpClient.
            HttpClient httpClient = HttpClients.createDefault();

            // Create a method instance.
            HttpGet get = new HttpGet(pathToAuthIdentity);

            HttpResponse response = httpClient.execute(get);

            int internResponseStatus = response.getStatusLine().getStatusCode();

            if(200 == internResponseStatus)
            {
                BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

                StringBuffer result = new StringBuffer();
                String line = "";
                while ((line = rd.readLine()) != null) {
                    result.append(line);
                }

                String userName = null;
                try {
                    JSONObject obj = new JSONObject(result.toString());
                    userName = obj.getString("SpotfireUser");
                } catch (JSONException ex) {
                }
                return new Identity(userName);                
            }else
            {
                return new AIdentity(null);                
            }

        } catch (IOException ex) {
            throw ex;
        } 
    }

    public class AIdentity implements IIdentity
    {
        private final String UserName;
        public AIdentity(String userName)
        {
            this.UserName = userName;
        }
        @Override
        public String getName() {
            return UserName;
        }

    }
}

这就是我使用这个类的方式

    import java.io.IOException;
    import java.security.Principal;
    import javax.servlet.http.*;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;


    public class SpotfireAuthFilter implements Filter {

        private static final String AUTHENTICATION_SERVICE_URL_PARAM = "AUTHENTICATION_SERVICE_URL";
        private static final String COOKIE_NAME_PARAM = "COOKIE_NAME";



        private ServletContext context;    
        private String[] SpotfireTicketNames = null;
        private String[] AuthServiceBaseURLs = null;

        private IAuthenticator AuthService;

        @Override
        public void init(FilterConfig fc) throws ServletException {
            context = fc.getServletContext();

            if(null == fc.getInitParameter(AUTHENTICATION_SERVICE_URL_PARAM) 
                || null == fc.getInitParameter(COOKIE_NAME_PARAM) )
            {
                throw new ServletException("Can't read filter initial parameters");
            }

            AuthServiceBaseURLs = fc.getInitParameter(AUTHENTICATION_SERVICE_URL_PARAM).split(",");
            SpotfireTicketNames = fc.getInitParameter(COOKIE_NAME_PARAM).split(",");
            AuthService = new Authenticator();

            if(SpotfireTicketNames.length != AuthServiceBaseURLs.length)
            {
                throw new ServletException(
                        String.format("Count of '%s' parameter don't equal '%s' parameter", 
                                COOKIE_NAME_PARAM, 
                                AUTHENTICATION_SERVICE_URL_PARAM));
            }

        }

        @Override
        public final void doFilter(
                ServletRequest servletRequest,
                ServletResponse servletResponse,
                FilterChain chain)  throws ServletException 
        {
            final HttpServletRequest request = (HttpServletRequest) servletRequest;
            final HttpServletResponse response = (HttpServletResponse) servletResponse;

            try 
            {
                doFilter(request, response, chain);
            } 
            catch (IOException | RuntimeException e) 
            {
              // Not possible to authenticate, return a 401 Unauthorized status code without any WWW-Authenticate header

              sendError(response, 401, "Unauthorized");
            }
        }

        @Override
        public void destroy() {
         // do nothing   
        }

        private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException 
        {

            String url = getAuthServiceURL(request);
            if(null != url)           
            {


                IIdentity identity = AuthService.doAuthentication(url);
                if(null != identity)
                {
                    String userName = identity.getName();
                    if(null != userName && !userName.equalsIgnoreCase(""))
                    {
                        Principal principal = createPrincipal(userName);

                        // Pass on the request to the filter chain and the authentication framework
                        // should pick up this priincipal and authenticate user
                        chain.doFilter(new WrappedHttpServletRequest(request, principal), response);


                    }
                    else
                    {
                        throw new IOException("Authentication failed");
                    }
                }else
                {
                    throw new IOException("Can't authenticate user by url " + url);
                }
            }
            else
            {
                throw new IOException("Can't find ticket to authenticate user.");
            }

            // Done!
            return;
        }

        private void sendError(HttpServletResponse response, int statusCode, String message) {
            try {
              response.sendError(statusCode, message);
            } catch (IOException e) {

            }
        }

        private String getAuthServiceURL(HttpServletRequest request) {

            Cookie[] cookies  = request.getCookies();
            for(int i =0; i< cookies.length; ++i)
            {
                for(int j =0; j< SpotfireTicketNames.length; ++j)
                {
                    if(cookies[i].getName().equalsIgnoreCase(SpotfireTicketNames[j]))
                    {
                        return String.format(AuthServiceBaseURLs[j], cookies[i].getValue());
                    }    
                }
            }
            return null;
        }


    private Principal createPrincipal(String username) 
    {

        // check does username contain domain/email/display name 
        return new APrincipal(username);
    }



    /**
     * A wrapper for {@link HttpServletRequest} objects.
     */
    private static class WrappedHttpServletRequest extends HttpServletRequestWrapper {

      private final Principal principal;

      public WrappedHttpServletRequest(HttpServletRequest request, Principal principal) {
        super(request);
        this.principal = principal;
      }

      @Override
      public Principal getUserPrincipal() {
        return this.principal;
      }

    } // WrappedHttpServletRequest
  }


    public class APrincipal implements Principal {
        private final String _username;

        public APrincipal(String username) {
           _username = username;
        }

        @Override
        public String getName() {
         return _username;   
        }

    }

还有这些初始参数

【讨论】:

  • 我会关注你用过滤器而不是 servlet 做了什么。此过滤器是否作为 SSO 工作,因此在需要从某个门户打开 web 播放器时无需实施另一个 SSO。提前致谢。
【解决方案2】:

你可以使用库Apache HTTP Components

doGet() 的简短示例(我没有编译):

import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
{
   String url="http://your.server.com/path/to/app?par1=yxc&par2=abc");
   HttpGet get=new HttpGet(url);
   httpClient = HttpClients.createDefault();
   // optional configuration
   RequestConfig config=RequestConfig.custom().setSocketTimeout(socketTimeoutSec * 1000).build();
    // more configuration

    get.setConfig(config);

    CloseableHttpResponse internResponse = httpClient.execute(get);

    int internResponseStatus = internResponse.getStatusLine().getStatusCode();

    InputStream respIn = internResponseEntity.getContent();
    String contentType = internResponseEntity.getContentType().getValue();

    // consume the response
}

【讨论】:

  • 感谢分享。我还没有编译它,但是,至少,你指出了在哪里看。
猜你喜欢
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2013-10-29
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
相关资源
最近更新 更多