React:使用BASIC身份验证实现登录

时间:2018-04-14 13:06:58

标签: javascript reactjs authentication basic-authentication fetch-api

我想创建一个包含登录信息的反应式网络应用。我的后端是通过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>);
    }
}

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

1 个答案:

答案 0 :(得分:1)

有很多可能的解决方案。您可以使用bind方法并传递绑定的get方法,并设置用户名和密码。因此,您获得的功能将接受usernamepassword作为参数

export function get(username, password, url)

而Context.Provider将传递绑定函数

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

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

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

我真的不认为你应该使用Context来做这种事情。事情是上下文对于UI逻辑是好的,这更多地是关于服务层。还有许多其他解决方案,包括在适当情况下将get作为道具传递,或者如果您将reduxredux-thunk一起使用,则将其作为thunk.withExtraArgument传递,但这实际上超出了您的问题的范围

相关问题