【问题标题】:React JS - How to authenticate credentials via a fetch statementReact JS - 如何通过 fetch 语句验证凭据
【发布时间】:2018-10-20 21:23:15
【问题描述】:

我的目标是创建一个运行 json Rest 服务的 React JS 登录页面。在 Postman 中,当我输入服务的 URL 时,将其设置为以 POST 方式运行,并将以下 JSON 输入到正文中: {用户名:“我的用户名”,密码:“我的密码”} ...返回一个令牌。所以在我的 fetch 子句中,我使用 JSON.stringify 将用户名和密码传递给服务器。

我是使用 Fetch 和 react 的新手,所以我的问题是,我如何开始验证各种用户,仅使用 react JS 和 fetch?我假设,我要在 Fetch 子句的第二个 then 内编写我的逻辑?

目前,我的页面接受任何凭据,并在单击提交按钮后将用户路由到登录页面。我有一个包含 fetch 的函数,现在在单击 onSubmit 按钮后调用 fetch 函数,该按钮现在获取令牌。

这是我的代码:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './Login.css';
import { withRouter } from 'react-router-dom';

class Login extends Component {

    constructor() {
        super();
        this.state = {
            data: [],
            username: "",
            password: "",
            token: "",
        };
    } //end constructor

    componentWillMount() {
    }

    componentDidMount() {
        this.fetchData();
    }

    fetchData() {
        fetch('http://theapi/api/auth', {
            method: 'POST',
            headers: {
                'Content-type': 'application/json',
            },
             body: JSON.stringify({
                username: 'myUserName',
                password: 'myPassword',
                Authorization: 'TheReturnedToken',
            })
        }) /*end fetch */
        .then(results => results.json())
        .then(data => this.setState({ data: data })

        )
    }

    //request the token
      requestAccessToken(data) {
        const loginInfo = '${data}&grant_type=password';
        return fetch('${API_URL}Token', {
          method: 'POST',
          headers: new Headers({
            'Content-Type': 'application/json',
          }),
          body: loginInfo,
        })
          .then((response) => response.json());
      }

      //authenticate request
      requestUserInfo(token) {
        return fetch('${API_URL}api/participant/userinfo', {
          method: 'GET',
          headers: new Headers({
            Authorization: 'Bearer ${token}',
          }),
        })
          .then((response) => response.json());
      }

    change = (e) => {
        this.setState({
            [e.target.name]: e.target.value
        });
    }; //end change

    onSubmit = (e) =>{
        this.fetchData();
        e.preventDefault();
        //console.log(this.state);
        this.setState({
             username: "",
             password: "",
            });

        this.props.history.push('/landing');
        };

    render() {
    console.log(this.state.data);
        return (
           <div>
                <div className="loginContainer">
                <h2>Member Login</h2>
                    <form>
                            <input
                            id="username"
                            name="username"
                            placeholder="User Name"
                            value={this.state.username}
                            onChange={e => this.change(e) }
                            className="form-control"
                            />  <br />

                            <input
                            id="password"
                            name="password"
                            type="password"
                            placeholder="Password"
                            value={this.state.password}
                            onChange={e => this.change(e) }
                            className="form-control"
                            />  <br />

                        <button onClick={e => this.onSubmit(e)} className="btn btn-primary">Submit</button>
                        </form>
                    </div>
            </div>
        );
      }
}

export default withRouter(Login);

如何开始让我的表单对各种用户进行身份验证?基本上,我试图让我的页面接受用户名和密码,如果两者匹配,然后将用户路由到登录页面。

【问题讨论】:

  • Fetch 不是 React 的概念。我建议在将 UI 引入之前了解如何通过 HTTP 进行通信。
  • 将 componentDidMount 代码移动到 onSubmit 这样当您点击提交按钮时,它将调用 fetch
  • 您应该在数据库中存储散列或加密密码,并让 API 进行密码比较。 React 应用程序应该只关心 API 是否说用户名/密码是好的。

标签: javascript json reactjs rest api


【解决方案1】:

不要将您的授权令牌放在正文中。把它放在页眉中。第一个函数将传入用户名、密码和身份验证类型(即grant_type=password)。然后我的第二个函数将使用它来验证请求。不再需要传递任何用户信息,因为我的 api 根据传入的令牌知道谁在请求。OAuth 2.0 is here 的当前文档,您可以找到有关使用带有 fetch at Mozilla's fetch documentation 的标头的更多信息.

// request the token
// subscribe to this event and use the returned json to save your token to state or session storage
export function requestAccessToken(data) {
  const loginInfo = `${data}&grant_type=password`;
  return fetch(`${API_URL}Token`, {
    method: 'POST',
    headers: new Headers({
      'Content-Type': 'application/x-www-form-urlencoded',
    }),
    body: loginInfo,
  })
    .then((response) => response.json());

    // in your case set state to returned token
}

// use said token to authenticate request
export function requestUserInfo(token) {
  return fetch(`${API_URL}api/participant/userinfo`, {
    method: 'GET',
    headers: new Headers({
      Authorization: `Bearer ${token}`,
    }),
  })
    .then((response) => response.json());
}

我也会推荐:

  1. 从 thunk 或 saga 调用 fetch,但这超出了问题的范围。

  2. 无需将令牌放在隐藏字段中。顺便说一句,这仍然可以访问。只需保持状态即可。您还可以做一些其他的事情来保护它,但这也超出了问题的范围。

【讨论】:

  • 我对发布的代码进行了一些修改。我将 fetch 放入一个函数中,现在在 onSubmit 事件中调用它。从 requestAccessToken 函数开始,${API_URL}Token 会是我的 API 的 URL 并附加了令牌对象吗?例如theapi/api/auth{token}。如果我们可以进一步讨论使用堆栈溢出聊天,请告诉我。我在想我在 fetchData 函数中设置的内容,可以使用您提供的 sn-p 来完成。
  • 不,请参阅我的示例中的 headers: new Headers( 部分。 ${API_URL} 只是我网址的一部分。我要求用户信息,正文或网址中没有参数。我在标头中传递不记名令牌,它根据该令牌返回用户信息。 ${token} 然而,实际上是来自 api 的令牌。
  • 我看到requestAccessToken有参数:data,data是包含对象的东西,就是用户的token。现在,- requestUserInfo 具有参数令牌。因此,为了获取 requestAccessToken 和 requestUserInfo 函数中包含的 fetch,${API_URL} 应该是我在 FetchData 函数中使用的 API 的 URL 的一部分吗?我想了解的是这两个函数是如何访问我的 API 的。请求和身份验证函数中的 URL 是否会像这样设置:theapi/api/auth/${API_URL}Token
  • ${API_URL} = 'https://api.mywebsite.com/' 因此,当在第二个函数中组合时,它会解析为 https://api.mywebsite.com/api/participant/userinfo,它会返回有关用户的各种其他信息,例如前端需要的名字、姓氏、用户角色和 ID。跨度>
  • 第一个函数是检索我的令牌并将其保存到会话存储中。第二个功能是在标头中使用该标记。我不再需要传递用户数据。 api 根据令牌知道谁在请求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 2023-03-27
  • 2016-08-08
  • 2021-07-03
相关资源
最近更新 更多