【问题标题】:Getting 404 error while call oAuth2 api in the browser在浏览器中调用 oAuth2 api 时出现 404 错误
【发布时间】:2018-04-24 10:16:29
【问题描述】:

我使用 ruby​​ on rails 制作 RESTful api,也使用 doorkeeper 处理身份验证和授权。如您所知,门卫会生成一些 OAuth2 api,而我需要使用的其中两个是 /users,它是发布请求和 /oauth/token,它们为我制作令牌。我制作的 api 是 post、get、put 在 postman 和 android studio 和 web 浏览器中工作得很好。 但是门卫生成的 post api /users 和 /oauth/token 在 web 浏览器中不起作用,但在 android studio 和 postman 上运行良好。 这让我很困惑。我在调用这个 api 时遇到的错误是 404,我检查了服务器上的 ruby​​ 生产日志,它说没有路由匹配。这里的字符串就是方法和路由的类型是正确的。

这是我在 reactjs 中使用的代码。我用过 axios:

var url="http://x.x.x.x/oauth/token";
    axios.post(url,{
        "username":"1",
        "password":"password",
        "grant_type":"password"
      },{headers:{"Content-Type":"application/json"}}).then( (response) => {
          console.log(response.data);
        })
        .catch( (error) => {
          console.log(JSON.stringify(error));
        });

并且还使用原始 jQuery 发出请求并得到相同的错误。我所有的 api 都运行良好,除了这两个 api:

var firstname = document.forms["registerForm"]["first_name"].value;
    var lastname = document.forms["registerForm"]["last_name"].value;
    var pass = document.forms["registerForm"]["password"].value;
    var passconfirm = document.forms["registerForm"]["password_confirmation"].value;


    var json_data = {
        "async": true,
        "crossDomain": true,
        "url": send,
        "method": "POST",
        "headers": {
            "content-type": "application/json",
        },
        "processData": false,
        "data":
        {
            "user": {
                "user_name": username,
                "password": pass,
                "password_confirmation": passconfirm,
                "user_type": "admin"
            },
            "profile": {
                "first_name": firstname,
                "last_name": lastname
            }
        }
    }

    $.ajax(json_data).done(function (response) {
        console.log(response);
    });
    console.log(json_data['data']);
    console.log(username);

此代码的输出 console.log(JSON.stringify(error));这是:

{"config":{"transformRequest":{},"transformResponse":{},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8"},"method":"post","url":"http://x.x.x.x/oauth/token.json","data":"{\"username\":\"1\",\"password\":\"password\",\"grant_type\":\"password\"}"},"request":{}}

我在浏览器中找到请求头和响应头:

Response Header:

Content-Type    
application/json; charset=UTF-8
Content-Length  
34
Connection  
keep-alive
Status  
404 Not Found
X-Request-Id    
d593b73f-eec8-41cd-95cd-e4459663358c
X-Runtime   
0.002108
Date    
Mon, 13 Nov 2017 11:19:26 GMT
X-Powered-By    
Phusion Passenger 5.1.11
Server  
nginx/1.12.1 + Phusion Passenger 5.1.11


Request headers (427 B) 
Host    
x.x.x.x
User-Agent  
Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/56.0
Accept  
text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Language 
en-US,en;q=0.5
Accept-Encoding 
gzip, deflate
Access-Control-Request-Method   
POST
Access-Control-Request-Headers  
Origin  
http://localhost:3000
Connection  
keep-alive

【问题讨论】:

  • 可以分享一下错误信息吗?
  • 这可能与CORS有关,您可以尝试使用 var url="http://x.x.x.x/oauth/token.json" 吗?
  • 是的,我刚刚将 json 添加到我的端点的末尾,但它不起作用,并且还像这样enable-cors.org/server_nginx.html 做了关于 CORS 的本教程并添加到我的代码中

标签: javascript ruby-on-rails ruby reactjs doorkeeper


【解决方案1】:

似乎是因为 CORS 政策。你可以rack-cores。 它是一个机架中间件,您将能够向受门卫保护的应用程序发出跨域请求

【讨论】:

    【解决方案2】:

    在检查了他们的docs 之后,您似乎需要将Content-Type 标头更改为application/x-www-form-urlencoded,并将数据更改为key=value 对:

    const data = 'username=1&password=password&grant_type=password'

    或者简单地说:

    const formData = {
      username: '1',
      password: 'password', 
      grant_type: 'password',
    }
    
    const data = Object.keys(formData)
      .map(prop => `${prop}=${formData[prop]}`)
      .join('&')
    

    最终结果是:

    var url="http://x.x.x.x/oauth/token";
    
    axios.post(url, data, {
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      }
    }).then( (response) => {
      console.log(response.data);
    })
    .catch( (error) => {
      console.log(JSON.stringify(error));
    });
    

    【讨论】:

    • 我测试了你的方法,但没有成功,我在 WWW-Authenticate 中得到回复,上面写着 Bearer realm="Doorkeeper", error="invalid_request", error_description="The request is missing a必需参数,包含不受支持的参数值,或者格式错误。”
    • @Sandro 他们的文档还提到要发送(grant_typeclient_idclient_secretcode..)你要发送这些道具吗?
    • 诀窍是 const data = Object.keys(formData) .map(prop => ${prop}=${formData[prop]}) .join('&')
    【解决方案3】:

    您需要在 OAuth 设置中进行配置以允许访问客户端 Web 应用程序。检查您在 api 响应中收到的日志或错误消息。

    【讨论】:

    • @Sandro 你找到解决办法了吗?
    • 不,我还在找,一位资深开发者说它可以来自门卫中的回调 url,但我不知道如何在门卫中配置回调 url。门卫有一些关于回调的理论文本,但没有关于它的技术文档。不知道该怎么做
    【解决方案4】:
        function login(username, password, returnUrl) {
    
        const formData = {
            grant_type:"password",
            client_id:"xxxxxxxx",
            client_secret: "xxxxxxxxx",
            redirect_uri:"xxxxxxxx.com/api/v1/accounts/profile/",
            username:username,
            password:password
        }
    
        const d = Object.keys(formData)
          .map(prop => `${prop}=${formData[prop]}`)
          .join('&')
    
        const requestOptions = {
            method: 'POST',
            headers: { 
                "Content-Type": "application/x-www-form-urlencoded",
                'Accept': 'application/json'
             },
            body: d
        };
    
        return fetch('xxx.com/o/token/', requestOptions)
            .then(handlePostResponse)
            .then(token => {
    
                // login successful if there's a user in the response
                if (token) {
                    token.token = token
                }
    
                console.log(token)
    
                return token;
            });
    
    }
    

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 1970-01-01
      • 1970-01-01
      • 2017-03-06
      • 1970-01-01
      • 2019-07-07
      • 2015-04-10
      • 2021-05-04
      • 1970-01-01
      相关资源
      最近更新 更多