javascript - react : Implement Login with BASIC Authentication

标签 javascript reactjs authentication basic-authentication fetch-api

我想创建一个包含登录名的 React 网络应用程序。我的后端是使用 JAX-RS 和 BASIC 身份验证实现的。这是 web.xmlResource 的片段。

<login-config>
    <auth-method>BASIC</auth-method>
</login-config>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>api</web-resource-name>
        <url-pattern>/api/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>ROLE</role-name>
    </auth-constraint>
</security-constraint>

<security-role>
    <role-name>ROLE</role-name>
</security-role>

资源:

@GET
@PermitAll
@Produces(MediaType.APPLICATION_JSON)
public List<OnlineStackDto> getData() {
    return dataService.getData();
}

来自 React 的所有请求都捆绑在一个文件 request.js 中。这里以 get 函数为例。

const user = 'username';
const pass = 'password';

export function get(url) {
    return fetch(url, 
        {
            method: 'GET',
            headers: {
                Authorization: "Basic " + btoa(user + ":" + pass)
            }
        }
    );
}

当然,硬编码用户名和密码不是以后部署应用程序的方式。该函数是这样调用的:

import {get} from "./request";
import React from "react";

export default class DataComponent extends React.Component {
    componentDidMount() {
        get('onlinestacks').then(data => this.setState({myData: data}));
    }
}

登录逻辑是使用react-routerReact 16.3 Context-API 实现的.因此,我可以使用 Consumer 访问每个组件中的用户名/密码。以下是如何设置和使用数据的示例。有关更完整的示例,请参阅 this question .

export default class App extends Component {

    constructor(props) {
        super(props);
        this.state = {
            user: {
                username: '',
                password: ''
            }
        };

        this.login = this.login.bind(this);
    }

    login(username, password) {
        this.setState({
            user: {
                username: username,
                password: password
            }
        });
    }

    render() {
        return (
            <UserContext.Provider value={this.state.user}>
                <Header/>
                /*Other Components*/
            </UserContext.Provider>
        );
    }

}

export default class Header extends React.Component {

    render() {
        return (<header>
            <UserContext.Consumer>{value =>
                <div className="username">{value.username}</div>
            }
            </UserContext.Consumer>
        </header>);
    }
}

我的问题是:
如何在我的请求中使用上下文中的用户名和密码, 每次我想发出请求时都必须传递它们?

最佳答案

对此有许多可能的解决方案。您可以使用 bind 方法并传递绑定(bind)的 get 方法,并设置用户名和密码。所以你得到的函数将接受 usernamepassword 作为参数

export function get(username, password, url)

你的 Context.Provider 将传递绑定(bind)函数

<UserContext.Provider value={get.bind(null,this.state.user,this.state.password)}>

要不触发回流,您可以解除绑定(bind)

login(username, password){
  this.setState({
        authenticatedGet: get.bind(null,username,password)
  });
}
//....
<UserContext.Provider value={this.state.authenticatedGet}>

不过,我真的不认为您应该将 Context 用于此类内容。问题是 Context 对 UI 逻辑有好处,这更多是关于服务层。还有许多其他解决方案,包括在适当的地方将 get 作为 prop 传递,或者如果您将 reduxredux-thunk 一起使用,将其作为 thunk 传递.withExtraArgument 但这确实超出了您的问题范围。

关于javascript - react : Implement Login with BASIC Authentication,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49831775/

相关文章:

php - 如何使用 Laravel Passport (5.3) 记录身份验证尝试

security - 安全存储和使用用户凭证测试环境的策略

javascript - href ="javascript:void(0)"与高级禁用链接

javascript - 下拉菜单编码 - 鼠标悬停

javascript - 在 react 中将事件监听器附加到 componentDidUpdate

javascript - React 和 Meteor "Uncaught TypeError: Cannot read property ' createElement' of undefined"

ubuntu 18.04 登录循环

JavaScript:根据媒体查询设置滚动位置变量

javascript - Azure 移动服务 - 从两个表读取并返回自定义响应对象

javascript - React 中的异步/等待