【问题标题】:spring websocket with digest authentication带有摘要身份验证的spring websocket
【发布时间】:2017-07-26 03:03:45
【问题描述】:

我使用 Spring security 来验证我的 spring websocket 服务器。它适用于Basic authentication,但当我更改为Digest authentication 时出现问题。我不知道在标题中添加什么。有人知道任何解决方案吗?

这是websocket客户端代码sn-p:

SockJsClient sockJsClient;
WebSocketStompClient stompClient;
List<Transport> transports = new ArrayList<>();
final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
headers.add("Authorization", "Basic YWRtaW46YWRtaW4=");
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
sockJsClient = new SockJsClient(transports);

stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
......

更新:

它可以很好地用于rest的digest,以下代码可以配置RestTempalte使用digest:

import java.net.URI;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.HttpClient;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

public class HttpComponentsClientHttpRequestFactoryDigestAuth extends HttpComponentsClientHttpRequestFactory {

    public HttpComponentsClientHttpRequestFactoryDigestAuth(HttpClient client) {
        super(client);
    }

    @Override
    protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
        return createHttpContext(uri);
    }

    private HttpContext createHttpContext(URI uri) {
        // Create AuthCache instance
        AuthCache authCache = new BasicAuthCache();
        // Generate DIGEST scheme object, initialize it and add it to the local auth cache
        DigestScheme digestAuth = new DigestScheme();
        // If we already know the realm name
        digestAuth.overrideParamter("realm", "myrealm");
        HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort());
        authCache.put(targetHost, digestAuth);

        // Add AuthCache to the execution context
        BasicHttpContext localcontext = new BasicHttpContext();
        localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
        return localcontext;
    }
}

获取休息模板:

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

public class RestTempleteConfig {

    public RestTemplate getRestTemplate() {
        CloseableHttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider())
                .useSystemProperties().build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryDigestAuth(
                client);

        return new RestTemplate(requestFactory);
    }

    private CredentialsProvider provider() {
        CredentialsProvider provider = new BasicCredentialsProvider();
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("admin", "admin");
        provider.setCredentials(AuthScope.ANY, credentials);
        return provider;
    }
}

使用休息模板:

RestTemplate restTemplate = new RestTempleteConfig().getRestTemplate();
String uri = "http://localhost:8080/login";
ResponseEntity<String> entity = restTemplate.exchange(uri, HttpMethod.GET, null, String.class);
System.out.println(entity.getBody());

【问题讨论】:

  • Digest算法你了解多少?这不仅仅是设置标题。
  • 客户端向服务器发送请求时,第一次收到401错误。然后客户端可以从响应头中获取领域和随机数以发送后续请求。我认为如果我发送正确的标题可能没问题,但很难得到随机数。但是使用摘要验证 websocket 的正确方法是什么?

标签: spring-security spring-websocket digest-authentication


【解决方案1】:

我已经找到了解决方案。在服务器端配置digest authenticationspring security,然后将客户端实现更改为:

RestTemplate restTemplate = new RestTempleteConfig().getRestTemplate();

SockJsClient sockJsClient;
WebSocketStompClient stompClient;
List<Transport> transports = new ArrayList<>();
final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();

StandardWebSocketClient websocketClient = new StandardWebSocketClient();
// add restTemplate first
transports.add(new RestTemplateXhrTransport(restTemplate));
transports.add(new WebSocketTransport(websocketClient));
sockJsClient = new SockJsClient(transports);

stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());

摘要是在rest template中配置的,我们需要做的是添加到Transport list中。您应该先添加rest template,然后添加websocket,因为这在创建sockJs url 时很重要。更多详情请参考this link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多