常见问题
是否可以从 Java servlet 的 doGet
方法发送 get 请求?我需要针对我的 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)。
为了允许我们的用户在 Web 应用程序内查看报告,我们使用 Spotfire WebPlayer(IIS Web 应用程序)和 JavaScript API。我们在 Web 应用程序中对用户进行身份验证,然后允许他们利用 JS API 向 WebPlayer 发出请求。为了使用已经经过身份验证的用户,我们根据 key 票证在 WebPlayer 上实现了自定义身份验证,如 here 中所述。 。因此,我们创建了由 Spotfire WebPlayer 加载并调用重写函数的 .NET 程序集。在此函数中,我们调用 Web API 服务来验证用户并获取有效的 Spotfire 用户名,然后我使用收到的用户名创建 IIdentity
。
当新版本的 TIBCO Spotfire 7.5 发布时,我们发现它们 removed支持自定义身份验证,因为它们changed架构,现在他们支持“external authentication ”。这种方法可以作为 Java servlet 来实现,用于验证用户身份,然后进行 Spotfire:
Retrieves the user name from the getUserPrincipal() method of javax.servlet.http.HttpServletRequest
所有这些迫使我们用 Java 重新编写逻辑。然而,我们不想改变身份验证的整体工作流程,并且我们希望坚持已经有效的票务模式。我是 Java servlet 的新手,所以我的目标是基于 servlet 实现相同的身份验证。他们有example其中 servlet 类具有方法 doGet
和 doPost
( link to zip with example )。我在这里假设我可以实现自己的 doGet
并向 Web API 发送请求以验证票证并取回用户名。
有意义吗?
最佳答案
最后我得到了这段代码。我实现了简单的过滤器而不是 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;
}
}
以及这些初始参数
关于java - 从 Java Servlet 向 Web API 发送 get 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36077981/