2016-02-16 36 views
6

Używam Angular2, aby uzyskać token dostępu z aplikacji back-end Java Spring. Mogę dostać token przez CURL, ale nie za pomocą formularza kątowego.Angular2 Jak zdobyć token wysyłając poświadczenia

curl localhost:8085/uaa/oauth/token --data "grant_type=password&scope=write&username=MY-USERNAME&password=MY-PASSWORD" --user user:pwd 

Włączyłem Cors na Java back-end tak:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { 
    final HttpServletResponse response = (HttpServletResponse) servletResponse; 
    response.setHeader("Access-Control-Allow-Origin", "*"); 
    response.setHeader("Access-Control-Allow-Credentials", "true"); 
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE, GET, HEAD, OPTIONS"); 
    response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, If-Modified-Since"); 
    chain.doFilter(servletRequest, servletResponse); 
} 

Mój kod kątowa wygląda następująco:

import {Injectable, Component} from 'angular2/core'; 
import {Observable} from 'rxjs/Rx'; 
import {Http, HTTP_PROVIDERS, Headers} from 'angular2/http'; 

@Component({ 
    viewProviders: [HTTP_PROVIDERS] 
}) 

@Injectable() 
export class Authentication { 
    token:string; 
    http:Http; 

    constructor(http:Http) { 
    this.token = localStorage.getItem('token'); 
    this.http = http; 
    } 

    login(username:String, password:String) { 

    var url = 'http://localhost:8085/uaa/oauth/token', 
     body = JSON.stringify({ 
      username: username, 
      password: password 
     }), 
     options = { 
      headers: new Headers({ 
       'credentials': 'true', 
       'grant_type': 'password', 
       'scope': 'write', 
       'Accept': 'application/json', 
       'Content-Type': 'application/x-www-form-urlencoded' 
      }) 
     }; 

     return this.http.post(url, body, options) 
     .map((res:any) => { 
      let data = res.json(); 
      this.token = data.token; 
      localStorage.setItem('token', this.token); 
     }); 
    } 
} 

Odpowiedź z serwera jest:

Request URL:http://localhost:8085/uaa/oauth/token 
Request Method:OPTIONS 
Status Code:401 Unauthorized 
Remote Address:[::1]:8085 

Odpowiedz

6

Można mieć dwa problemy:

  1. OPTIONS odbierane jest wywołanie inspekcji wstępnej. Standard CORS stwierdza, że ​​połączenia typu preflight nie powinny obejmować uwierzytelniania. Jeśli twój serwer nie jest skonfigurowany do obsługi tego, otrzymasz odpowiedź 401. Jeśli masz kontrolę nad serwerem, powinieneś być w stanie dodać coś, co umożliwi połączenie przez OPTIONS. Z nginx można dodać coś takiego:

    if ($request_method = 'OPTIONS') {return 200;}

    Nie jestem pewien jesteś szczególności serwera.

  2. Czy jesteś pewien, że wysyłasz poświadczenia we właściwy sposób? Wygląda na to, że przesyłasz wszystko jako indywidualne nagłówki, a nie dane zakodowane w formie, tak jak w przypadku żądania curl. To zadziałało dla mnie:

    var headers = new Headers(); 
    headers.append('Content-Type', 'application/x-www-form-urlencoded'); 
    
    var credentials = "grant_type=authorization_code 
           + "&credentials=true" 
           + "&scope=write" 
           /* etc. */ 
    
    
    this.http.post('http://some.url', credentials, { headers: headers }) 
        .subscribe((res) => token = res.json()) 
    
2

Powinieneś podać wskazówki dotyczące nazwy użytkownika/hasła w nagłówku Authorization ze schematem "Basic". Wartość musi zakodowane base64 z funkcją btoa:

headers.append('Authorization', 'Basic ' + btoa('username:password'); 

Ponadto po alook na żądanie curling, wydaje się, że to, co można umieścić w nagłówku należy podać w polu danych. Można to zrobić za pomocą klasy UrlSearchParams.

See rhis pytanie o więcej informacji: