【问题标题】:Restful api how to pass info after basic http authRestful api如何在基本http auth之后传递信息
【发布时间】:2016-03-14 21:21:21
【问题描述】:

我正在构建一个移动应用程序和 Restful API,我希望该应用程序的用户能够在没有身份验证的情况下获取他想要的任何资源。但是如果他想做 POST,他必须输入他的用户名并通过。 我已经通过在web.xml 中放置一个过滤器进行了 HTTP 基本身份验证。

<filter>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>org.service.RestAuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/webapi/*</url-pattern>
</filter-mapping>

还有课程

public class AuthenticationService {
ClientsService s = new ClientsService();
public boolean authenticate(String authCredentials) {

    if (null == authCredentials)
        return false;
    // header value format will be "Basic encodedstring" for Basic
    // authentication. Example "Basic YWRtaW46YWRtaW4="
    final String encodedUserPassword = authCredentials.replaceFirst("Basic"
            + " ", "");
    String usernameAndPassword = null;
    try {
        byte[] decodedBytes = Base64.decode(
                encodedUserPassword);
        usernameAndPassword = new String(decodedBytes, "UTF-8");
    } catch (IOException e) {
        e.printStackTrace();
    }
    final StringTokenizer tokenizer = new StringTokenizer(
            usernameAndPassword, ":");
    final String username = tokenizer.nextToken();
    final String password = tokenizer.nextToken();
    boolean authenticationStatus =s.auth(username, password);

    return authenticationStatus;
}
}

和过滤器

public class RestAuthenticationFilter implements javax.servlet.Filter {
public static final String AUTHENTICATION_HEADER = "Authorization";

@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filter) throws IOException, ServletException {
    if (request instanceof HttpServletRequest) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String authCredentials = httpServletRequest
                .getHeader(AUTHENTICATION_HEADER);

        // better injected
        AuthenticationService authenticationService = new AuthenticationService();

        boolean authenticationStatus = authenticationService
                .authenticate(authCredentials);

        if (authenticationStatus) {
            filter.doFilter(request, response);

        } else {
            if (response instanceof HttpServletResponse) {
                HttpServletResponse httpServletResponse = (HttpServletResponse) response;
                httpServletResponse
                        .setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            }
        }
    }
}

@Override
public void destroy() {
}

@Override
public void init(FilterConfig arg0) throws ServletException {
}
}

我需要知道的是:如何在身份验证后将用户名和密码或者只是客户端的 id 传递给 Restful 的方法。

【问题讨论】:

  • 身份验证后,您从哪里访问您的 REST 服务?如果您可以从那里访问您的会话,您可以尝试在成功身份验证后将您的客户端 ID 存储在会话中,然后再检索它。
  • 身份验证后,它会将我重定向到我要求的资源。例如 ..../restful/offers ,我不是 restful 方面的专家,但我认为我不应该在会话中存储任何想法吗?
  • 是否可以为 POST 请求使用不同的路径?如果是这样,您只能将RestAuthenticationFilter 映射到此路径。我不确定这个提议是否违反了 REST 原则。

标签: java rest authentication servlets jakarta-ee


【解决方案1】:

与我的评论不同的解决方案:您可以查找 HTTP 请求方法,然后决定是否调用身份验证方法:

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filter) throws IOException, ServletException {
    if (request instanceof HttpServletRequest) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String authCredentials = httpServletRequest
                .getHeader(AUTHENTICATION_HEADER);

        boolean authenticationStatus;

        // check request method
        if (((HttpServletRequest).request).getMethod().equals("GET")) {
            authenticationStatus=true;
        } else {
            // better injected
            AuthenticationService authenticationService =
                  new AuthenticationService();
            authenticationStatus = authenticationService
                .authenticate(authCredentials);
        }

        if (authenticationStatus) {
            filter.doFilter(request, response);

        } else {
            if (response instanceof HttpServletResponse) {
                HttpServletResponse httpServletResponse = (HttpServletResponse) response;
                httpServletResponse
                        .setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            }
        }
    }
}

更新:

使用 JAX-RS 获取更多请求信息的可能解决方案可能如下所示:

import javax.ws.rs.*;
import javax.ws.rs.core.Context;

@GET
@Path("offers")
@Produces("application/xml")
public YourList getOffers(@Context HttpServletRequest request)
{
    System.out.println("request to "+request.getRequestURI()+" , Auth: "+request.getHeader(AUTHENTICATION_HEADER));

// more stuff for obtaining data
}

【讨论】:

  • 感谢您的回答,这是一个非常好的主意,但我的问题是在身份验证完成后如何将用户名和密码传递给 GET 或 POST 方法?
  • 您可以将HttpServletRequest的引用传递给您的服务方法,然后使用getHeader(AUTHENTICATION_HEADER)
  • 有时解决方案就在那里,但你看不到它:).. 谢谢你解决了我的问题。
猜你喜欢
  • 2014-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
相关资源
最近更新 更多