简体   繁体   English

当 axios 在 React 中请求时,Ruby on Rails 不包含 header 上的授权令牌,但它确实适用于 Postman

[英]Ruby on Rails does not include Authorization token on header when request by axios in React, but it does work with Postman

I'm currently working on a backend API using Ruby on Rails, Devise, and Devise-JWT, with NextJS on the frontend client, using axios for requests.我目前正在后端 API 使用 Rails 上的 Ruby、Devise 和 Devise-JWT,在前端客户端上使用 NextJS,使用 axios 进行请求。 I've been trying to access the Authorization token from the header (once the user logs in), to then store the token into localhost but it doesn't come within the header on the request.我一直在尝试从 header 访问授权令牌(一旦用户登录),然后将令牌存储到本地主机中,但它不在请求的 header 中。 Although, the post login request does supply an Auth on the header when testing on Postman. What am I missing?虽然,在 Postman 上测试时,登录后请求确实在 header 上提供了 Auth。我错过了什么? Thanks in advance!提前致谢!

expose Authorzation header using this: expose: ['Authorization'] in the rack corse config do this:使用这个公开 Authorzation header:在 rack corse 配置中expose: ['Authorization']这样做:

Rails.application.config.middleware.insert_before 0, "Rack::Cors" do
  allow do
    origins '*'
    resource '*', headers: :any, methods: [:get, :post, :options, :patch, :delete], expose: ['Authorization']
  end
end

https://glaucocustodio.github.io/2016/01/20/dont-forget-to-expose-headers-when-using-rack-cors/ https://glaucocustodio.github.io/2016/01/20/dont-forget-to-expose-headers-when-using-rack-cors/

It would help to see the code you implemented the Axios user auth for the frontend.查看您为前端实现 Axios 用户身份验证的代码会有所帮助。

But maybe this can help.但也许这会有所帮助。

//---------- Reducer -----------
// In your reducer
const authReducer = (state, { type, payload }) => {
  switch (type) {
    case 'LOGIN': {
      localStorage.setItem('authToken', JSON.stringify(payload.auth_token));
      localStorage.setItem('authEmail', JSON.stringify(payload.email));
      return {
        authToken: payload.auth_token,
        authEmail: payload.email,
      };
    }
    case 'YOUROTHER': {
      return {  };
    }
    default: {
      
    }
  }
};

export default authReducer;
//-------------------------------

//---------- Contexts -----------
// In your Contexts auth.js file
import authReducer from '../reducers/auth';

const AuthStateContext = React.createContext();
const AuthDispatchContext = React.createContext();

const token = JSON.parse(localStorage.getItem('authToken'));
const email = JSON.parse(localStorage.getItem('authEmail'));
const initialState = {
  isLoggedIn: !!token,
  authToken: token ? token : null,
  authEmail: email ? email : null,
};

const AuthProvider = ({ children }) => {
  const [state, dispatch] = React.useReducer(authReducer, initialState);
  return (
    <AuthStateContext.Provider value={state}>
      <AuthDispatchContext.Provider value={dispatch}>
        {children}
      </AuthDispatchContext.Provider>
    </AuthStateContext.Provider>
  );
};
//-------------------------------

//--------- App.js file ---------
// Then wrap the App.js like:
import { AuthProvider } from './contexts/auth';

function App(props) {
  return (
    <AuthProvider>
      <Main {...props} />
    </AuthProvider>
  );
}
//-------------------------------

//------- Your Login Component -------
// Imports
import { useAuthDispatch } from '../../contexts/auth';

// Axios handler 
const baseUrl = 'http://localhost:3001/';
const login = payload => axios.post(`${baseUrl}api/v1/login`, payload);
const authApi = {
  login,
};

// Auth Header Function
const setAuthHeaders = () => {
  // axios request try this
  axios.defaults.headers = {
    Accept: 'applicaion/json',
    'Content-Type': 'application/json',
  };
  const token = JSON.parse(localStorage.getItem('authToken'));
  const email = JSON.parse(localStorage.getItem('authEmail'));
  //Add token & email to axios header
  if (token && email) {
    axios.defaults.headers['X-Auth-Email'] = email;
    axios.defaults.headers['X-Auth-Token'] = token;
  }
};

// Login 
const Login = () => {
  const [initialValues, setInitialValues] = useState({
    email: '',
    password: '',
  });
  
  const authDispatch = useAuthDispatch();
  //const userDispatch = useUserDispatch();

  const handleLogin = async values => {
    const { /*eg. email, password*/ } = values;
    try {
      const {
        data: { user, /* should include:*/ auth_token },
      } = await authApi.login({ user: { email, password } });
      // your dispatch with payload: auth_token
      authDispatch({ type: 'LOGIN', payload: { auth_token, email } }); // passing the token & email via Dispatch
      // The user: { email, password } comes from the userDispatch
      setAuthHeaders(); // Auth Header Func
    } catch (error) {
      
    };

    return (
      <>
        {/* your jsx code */}
      </>
    );
  }
};

export default Login;

//--- # Your Login Component ---

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM