Angular2如何通过发送凭证获取令牌

时间:2016-02-16 20:42:21

标签: http curl spring-security oauth-2.0 angular

我使用Angular2从Java Spring后端应用程序获取访问令牌。 我可以通过CURL获取令牌,但不能通过Angular形式获取。

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

我在Java后端启用了Cors:

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

My Angular代码如下所示:

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

服务器的响应是:

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

4 个答案:

答案 0 :(得分:7)

您可能有两个问题:

  1. OPTIONS来电是预检电话。 CORS标准规定预检调用不应包括身份验证。如果您的服务器未设置为处理该服务器,您将收到401响应。如果您可以控制服务器,则应该能够添加一些内容以允许OPTIONS调用。使用NGINX,您可以添加以下内容:

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

    不确定您是否是特定服务器。

  2. 您确定以正确的方式发送凭据吗?看起来您将所有这些作为单独的标头发送而不是像curl请求一样的表单编码数据。这对我有用:

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

答案 1 :(得分:2)

您应该在授权标题中使用" Basic"提供用户名/密码提示。方案。该值必须使用带有btoa函数的base64编码:

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

此外,在完成你的卷曲请求之后,似乎应该在有效负载中提供你放入标题的内容。这可以使用UrlSearchParams类完成。

有关详细信息,请参阅此问题:

答案 2 :(得分:1)

这是正在运行的Nginx default.config的以下代码。

    var time = target?.date ?: 0L

    var calendar = Calendar.getInstance()
    calendar.timeInMillis = time

    LocalDate.ofYearDay(calendar.get(Calendar.YEAR), calendar.get(Calendar.DAY_OF_YEAR)).format(dateTimeFormatter)

答案 3 :(得分:0)

问题可能出在你的角度服务中。我认为您不应该将正文作为包含用户名和密码的对象发送,但是您应该发送包含" grant_type"," username"和#34;密码"。 这是我的工作服务方法的示例:

    postAuth(url: string, data?: LoginCredentials){

    let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });  
    let options = new RequestOptions({ headers: headers });

    //here I am setting username and password which I got from html form
    var body = "grant_type=password&username="+ data.Email + 
               "&password=" + data.Password; 

    return this.http.post(url, body, options);
  }