【问题标题】:Angular2 How to get token by sending credentialsAngular2如何通过发送凭据获取令牌
【发布时间】:2016-05-28 07:45:10
【问题描述】:

我正在使用 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);
}

我的 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

【问题讨论】:

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


    【解决方案1】:

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

    upstream book_up {
        server localhost:3002; 
    }
    
    server
    {
    
        location /login {
            proxy_pass http://book_up/book/user/login;
        }
        location /health {
            proxy_pass http://book_up/book/health;
        }
    
        location /book {
            auth_request /auth;
            proxy_pass http://book_up$request_uri;
        }
    
        location = /auth {
            if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            #
            # Custom headers and headers various browsers *should* be OK with but aren't
            #
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            #
            # Tell client that this pre-flight info is valid for 20 days
            #
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
         }
         if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
         }
         if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
         }
            proxy_pass http://book_up/book/user/auth/;
            proxy_set_header Content-Length "";
            proxy_set_header   X-Original-URI $request_uri;
        }
    }
    

    【讨论】:

      【解决方案2】:

      问题可能出在您的角度服务中。我认为您不应该将正文作为包含用户名和密码的对象发送,而应该发送包含“grant_type”、“username”和“password”的字符串。 这是我的工作服务方法的示例:

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

      【讨论】:

        【解决方案3】:

        您应该在“基本”方案的授权标头中提供用户名/密码提示。该值必须使用 btoa 函数以 base64 编码:

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

        此外,在查看了您的 curling 请求之后,您在标头中放入的内容似乎应该在有效负载中提供。这可以使用 UrlSearchParams 类来完成。

        查看 rhis 问题了解更多详情:

        【讨论】:

          【解决方案4】:

          你可能有两个问题:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-10-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-13
            • 1970-01-01
            • 2015-05-27
            相关资源
            最近更新 更多