React 和 Redux HTTP 标头授权

Posted

技术标签:

【中文标题】React 和 Redux HTTP 标头授权【英文标题】:React and Redux HTTP Header Authorization 【发布时间】:2017-01-03 06:34:53 【问题描述】:

我正在尝试使用我的 API 后端设置 React 身份验证。 API 后端使用电子邮件和密码,并为每个新用户创建一个令牌。所有这些都是通过直接 JSON 而不是 JWT 提供的,所以我使用 Auth0 tut 和这个 Stack q/a 作为起点。

我的第一个目标是进行简单的登录和重定向。我连接了动作/减速器,现在我正在调用 API。我正在使用基本的身份验证调用并将其转换为 64 位字符并通过标头发送。这些都是通过 Postman 测试和工作的。

当我执行当前的 React 设置时,它会在控制台中显示 “Fetching”,但不会出现 “I'm here.”,然后页面会简单地重新加载.我不确定在哪里解决这个问题并获得它的授权和重定向。有什么想法我哪里出错了吗?

HomePage.js(容器)

class HomePage extends React.Component 
 constructor(props) 
  super(props);
 

 render() 
  const  dispatch, isAuthenticated  = this.props;
 return (
   <div>
     < HomeHeader onLogin=this.props.onLogin />
   </div>
  );
 


 function mapStateToProps(state) 
  return  loginResponse: state.loginResponse ;
 

 function mapDispatchToProps(dispatch) 
 return 
   onLogin: (creds) => dispatch(loginUser(creds)),
 ;


export default connect(
mapStateToProps,
mapDispatchToProps
)(HomePage);

AuthorizationActions.js(动作)

function requestLogin(creds) 
 return 
  type: types.LOGIN_REQUEST,
  isFetching: true,
  isAuthenticated: false,
  creds
 

function receiveLogin(user) 
 return 
  type: types.LOGIN_SUCCESS,
  isFetching: false,
  isAuthenticated: true,
  id_token: user.id_token
 


export function loginUser(creds) 
 **console.log("Fetching");**
 const hash = new   Buffer(`$creds.username:$creds.password`).toString('base64')

return fetch('http://api.xxx.dev/sessions', 
  method: 'POST',
  headers: 
    'Content-Type': 'application/json',
    'Authorization': 'Basic $hash'
  ,
 )
  .then(response => 
    **console.log("I'm here");**
    if(response.status >= 200 && response.status < 300)
      console.log("Response; ", response);
      // Dispatch the success action
      dispatch(receiveLogin(user));
      localStorage.setItem('id_token', user.id_token);
     else 
      const error = new Error(response.statusText);
      error.response = response;
      dispatch(loginError(user.message))
      throw error;
    
  )
  .catch(error =>  console.log('Request Failed: ', error););
 

AuthorizationReducer.js(减速器)

import  browserHistory  from 'react-router';
import Immutable from 'immutable';

const initialState = new Immutable.Map(
 username: '',
 password: '',
 isLoggingIn: false,
 isLoggedIn: false,
 isFetching: false,
 error: null,
 isAuthenticated: localStorage.getItem('id_token') ? true : false
);

function authenticationReducer(state = initialState, action) 
 switch ( action.type ) 
 case 'LOGIN_REQUEST':
  return  ...state,
      isFetching: true,
      isAuthenticated: false,
      user: action.creds
  
 case 'LOGIN_SUCCESS':
  return 
    ...state,
    browserHistory: browserHistory.push('/dashboard')
  
 case 'LOGIN_FAILURE':
  return alert('Crap, there are login failures');
 default:
  return state;
 

export default authenticationReducer;

configureStore.js(商店)

const middleware = applyMiddleware(
  thunk,
  apiMiddleware,
  global.window ? logger : store => next => action => next( action )
);
const store = createStore( reducers, initialState, compose(middleware,    window.devToolsExtension ? window.devToolsExtension() : f => f  ))

AuhorizeLogin.js 组件

 constructor(props, context) 
  super(props, context);
  this.state = ;
  this._login = this._login.bind(this);
 

 _login(e) 
  e.preventDefault;
  const email = this.refs.email;
  const password = this.refs.password;
  const creds =  email: email.value.trim(), password: password.value.trim() ;
  this.props.onLoginClick(creds);

HomeHeader.js 组件

 `_handleChange(eventKey) 
< AuthorizeLogin onLoginClick=this.props.onLogin/>);
`

HomePage.js 容器

constructor(props) 
 super(props);

render() 
 const  dispatch, isAuthenticated  = this.props;
 return (
 ...
 < HomeHeader onLogin=this.props.onLogin />
 ...
 )


function mapStateToProps(state) 

return 
 loginResponse: state.loginResponse,
 ;


function mapDispatchToProps(dispatch) 
 return 
  onLogin: (creds) => dispatch(loginUser(creds)),
 ;


export default connect(
 mapStateToProps,
 mapDispatchToProps
 )(HomePage);

【问题讨论】:

您提到页面重新加载;您是否使用了form 标签而忘记了event.preventDefault() 我在组件的onClick函数中添加了。如果他们调用另一个操作,我是否需要将其添加到我的操作或减速器中的某个位置? 你能显示那个代码吗?我认为问题可能出在您的 HomeHeader 组件中。 我更新了上面的代码。它应该触发“dispatch(receiveLogin(user));”在 LoginUser 中接收成功,然后重定向。 这里的 SO 帖子代码太多。我仍然看不到您的所有代码,我怀疑您发布的大部分内容甚至与您的问题无关。对于HomeHeader 组件,我什至不确定我在看什么;有些失踪?尝试创建一个最小的可重现场景或在 SO 之外解决这个问题。 【参考方案1】:

试试return fetch('http://api.xxx.dev/sessions'...。 未经测试,但它应该让你“我在这里”。 最终,包装箭头函数

【讨论】:

试过这个。接得好。现在得到这个错误:(程序):1未捕获(承诺)错误:动作必须是普通对象。使用自定义中间件进行异步操作。 我建议您继续阅读:Async Actions

以上是关于React 和 Redux HTTP 标头授权的主要内容,如果未能解决你的问题,请参考以下文章

使用 jwt 授权反应 js 在标头中添加授权时遇到问题?

授权标头在获取中不起作用 - React Native

路由/重定向不在 React Router 4 和 Redux 授权中呈现

Axios 和 Wufoo:从 React 发布时“不允许请求标头字段授权”

缺少响应提取响应的授权标头

如何在 React 组件中向 Apollo 客户端添加新的授权标头?