【问题标题】:Apache CFX Basic Authentication HP Quality CenterApache CXF 基本身份验证 HP Quality Center
【发布时间】:2015-01-26 16:48:14
【问题描述】:

我正在使用 Apache CFX 编写一个到 HP Quality Center 的 REST 连接器。当向服务器发出请求时,我想使用 CFX 基础架构进行抢先式身份验证

HP Quality Center 使用基于 Basic 的身份验证机制。要进行身份验证,将使用标准基本身份验证标头将获取请求发送到 http:///qcbin/authentication-point/authenticate。然后服务器返回一个必须包含在所有后续请求中的 cookie(“LWSSO”)。在进行身份验证之前从服务器请求资源将导致带有 WWW-Authenticate 标头的 401,其中包含身份验证点 URI(例如 LWSSO realm="http://:80/qcbin/authentication-point)。

理想情况下,我想创建一个 CFX HttpAuthProvider 或拦截器,它通过拦截 401 响应、解析 WWW-Authenticate 标头并在为所有后续请求缓存 cookie 之前在身份验证点 URI 上执行请求来处理身份验证。

这将允许我使用工厂模式创建一个干净的基于代理的 API。例如:

public QualityCenter create(String url, String username, String password) {
    JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
    bean.setAddress(url);
    bean.setUsername(username);
    bean.setPassword(password);
    bean.setServiceClass(QualityCenter.class);      

       // TODO: Setup authentication modules here that use AuthPolicy for credentials.

    return bean.create(QualityCenter.class);
}

我似乎无法弄清楚这是否可行以及在哪里最好地实现该功能。

【问题讨论】:

    标签: apache authentication cookies reset basic-authentication


    【解决方案1】:

    我最终在不使用 Apache CXF 的情况下解决了这个问题——而是选择了 Jersey。

    我通过创建两个 JAXRS 过滤器来做到这一点。第一个过滤器拦截来自服务器的 401 响应,跟随在“WWW-Authenticate”标头中返回的认证点地址并执行 BASIC 认证。然后将原始请求重播到服务器。

    这个等式的第二部分是另一个过滤器,用于处理会话 cookie 的维护。因此,当重放初始请求时,身份验证 cookie 存在。

    这两个过滤器如下所示:

    class AuthenticationFilter implements ClientResponseFilter {
    
    private final String username;
    private final String password;
    
    public AuthenticationFilter(String username, String password) {
        this.username = username;
        this.password = password;
    }
    
    @Override
    public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
        if (responseContext.getStatus() == Response.Status.UNAUTHORIZED.getStatusCode()) {
            String header = responseContext.getHeaders().getFirst(WWW_AUTHENTICATE);
    
            // Check if we have been given the authentication redirect go-ahead.
            if (!header.startsWith("LWSSO")) {
                return;
            }
    
            String authUri = header.substring(13, header.length() - 1);
            Client client = ClientBuilder.newClient(requestContext.getConfiguration());
            String credentials = "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
            Response response = client.target(authUri).path("authenticate").request(MediaType.TEXT_PLAIN_TYPE).header(AUTHORIZATION, credentials).get();
            if (response.getStatus() == Response.Status.OK.getStatusCode()) {
                URI uri = requestContext.getUri();
                MediaType mediaType = requestContext.getMediaType();
                String method = requestContext.getMethod();
                NewCookie cookie = response.getCookies().get("LWSSO_COOKIE_KEY");
                MultivaluedMap<String, Object> headers = requestContext.getHeaders();
                headers.remove(WWW_AUTHENTICATE);
                Invocation.Builder builder = requestContext.getClient().target(uri).request(mediaType).headers(headers).cookie(cookie);
    
                Invocation invocation;
                if (requestContext.getEntity() != null) {
                    invocation = builder.build(method, Entity.entity(
                            requestContext.getEntity(), mediaType));
                } else {
                    invocation = builder.build(method);
                }
    
                Response replayed = invocation.invoke();
                responseContext.setStatus(replayed.getStatus());
                responseContext.setStatusInfo(replayed.getStatusInfo());
                if (replayed.hasEntity()) {
                    responseContext.setEntityStream(replayed
                            .readEntity(InputStream.class));
                }
                responseContext.getHeaders().clear();
                responseContext.getHeaders()
                        .putAll(replayed.getStringHeaders());
            }
        }
    }}
    
    
    class SessionFilter implements ClientRequestFilter, ClientResponseFilter {
    
        private final Map<String, NewCookie> cookies = new HashMap<String, NewCookie>();
    
        @Override
        public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
            cookies.putAll(responseContext.getCookies());
        }
    
        @Override
        public void filter(ClientRequestContext requestContext) throws IOException {
            for(NewCookie cookie: cookies.values()) {
                requestContext.getHeaders().add("Cookie", cookie);          
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-25
      • 2011-05-05
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 2012-03-05
      • 2016-02-08
      • 2012-02-04
      相关资源
      最近更新 更多