0

J'utilise sécurité Spring pour authentifier mon serveur spring websocket. Cela fonctionne bien avec le Basic authentication, mais il s'est mal passé lorsque j'ai changé pour Digest authentication. Je ne sais pas quoi mettre dans les en-têtes. Est-ce que quelqu'un connaît des solutions?websocket de printemps avec l'authentification Digest

C'est le code client websocket extrait:

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

Mise à jour:

Il fonctionne bien avec digérer pour le repos, les codes suivants peuvent configurer RestTempalte utiliser digérer:

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

Obtenez un modèle de repos:

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

Utiliser le modèle de repos:

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

Que savez-vous à propos de l'algorithme Digest? Ce n'est pas juste de définir un en-tête. – holmis83

+0

Lorsqu'un client envoie une requête au serveur, il recevra une erreur 401 pour la première fois. Alors le client peut obtenir le domaine et le nonce de l'en-tête de réponse pour envoyer une demande suivante. Je pense que c'est peut-être bien si j'envoie l'en-tête correct mais c'est difficile d'obtenir le nonce. Mais quelle est la bonne façon d'authentifier websocket avec digest? –

Répondre

0

J'ai trouvé la solution. Configurer digest authentication avec spring security du côté sever, puis modifiez la mise en œuvre du client à ceci:

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

Le résumé est configuré dans le rest template, ce que nous devons faire est d'ajouter à Transport list. Et vous devez d'abord ajouter rest template, puis websocket, car il est important lors de la création de l'URL sockJs. Plus de détails se réfèrent à this link.