0

我使用彈簧安全來驗證我的spring websocket服務器。它適用於Basic authentication,但當我更改爲Digest authentication時出錯。我不知道該把什麼放入標題。有人知道任何解決方案嗎?具有摘要式身份驗證的彈簧websocket

這是WebSocket的客戶端代碼片段:

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()); 
...... 

更新:

它與消化休息效果很好,下面的代碼可以配置RestTempalte使用摘要:

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; 
    } 
} 

使用REST模板:

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()); 
+1

你對Digest算法有什麼瞭解?這不僅僅是設置標題。 – holmis83

+0

當客戶端向服務器發送請求時,它將首次收到401錯誤。然後,客戶端可以從響應頭獲得領域和隨機數以發送後續請求。我認爲如果我發送正確的標題可能沒有問題,但很難得到隨機數。但是,用摘要驗證websocket的正確方法是什麼? –

回答

0

我已經找到了解決方案。在服務器端配置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網址時它很重要。更多細節請參考this link