gpt4 book ai didi

javascript - 需要帮助尝试在 native react 中刷新我的 token

转载 作者:行者123 更新时间:2023-12-05 00:31:13 31 4
gpt4 key购买 nike

我认为这是一项简单的任务,存储我的 token ,设置一个计时器并在计时器到期时获取 token ,我错了,在看了几篇关于如何解决这个问题的文章之后,我现在 super 迷路,我在存储我的 token (或同时存储我的 token (或同时存储用户名数据和 token ?不再确定)以及在 token 过期时刷新 token 方面需要帮助。
是的,我在堆栈溢出中看到了很多与此相关的问题,但其中许多与特定问题有关,而不是如何去做。
我的应用程序通过 microsoft graph 从 api (net core 2.0) 连接到 office 365。
在我的应用程序上,我得到了这段代码来从 api 获取数据,传递参数我的用户名和密码

  async ApiLogin(loginRequestObject: LoginRequest) {
var serviceResult = new ServiceResult();
await NetInfo.fetch().then(async state => {
var param = JSON.stringify(loginRequestObject);
if (state.isConnected) {
try {
await fetch(ServiceProperties.URLauthentication, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: param,
})
.then(response => {
return response.json();
})
.then(responseJson => {
if (JSON.stringify(responseJson) != null) {
serviceResult.Success = true;
serviceResult.Message = 'Service Authentication ok';
serviceResult.ResponseBody = responseJson;
serviceResult.StatusCode = 0;
} else {
serviceResult.Success = false;
serviceResult.Message = 'Service Authentication not ok';
serviceResult.ResponseBody = null;
serviceResult.StatusCode = -100;
}
});
} catch (error) {
serviceResult.Success = false;
serviceResult.Message = 'Service Authentication not ok';
serviceResult.ResponseBody = null;
serviceResult.StatusCode = -999;
}
} else {
serviceResult.Success = false;
serviceResult.Message = 'Service internet not ok';
serviceResult.ResponseBody = null;
serviceResult.StatusCode = -1;
}
});
console.log(JSON.parse(serviceResult.ResponseBody));
return serviceResult;
}
结果是这样的。
{"Username":"sensitive data","DisplayName":"sensitive data","GivenName":"sensitive data","SurName":"sensitive data","Email":"sensitive data","Token":"ZSI6Im42aGRfdDVGRHhrSzBEVklJUXpxV09DWHZ4dWc0RlhWVkI4ZVJ6dEFsWDAiLCJhbGciOiJSUzI1NiIsIng1dCI6IlNzWnNCTmhaY0YzUTlTNHRycFFCVEJ5TlJSSSIsImtpZCI6IlNzWnNCTmhaYm5ldC8zOTBmODU5NS1kZTFlLTRmNmQtYTk1NC0yNWY2N5MjkwMTYsImV4cCI6MTU5MjkzMjkxNiButVBqe3E3QwcBr1P0G_dWyC9ASQU0psGDPnsQPHp0T070ROZ_mcPitgquNfsO5JZ8-o056l_aePhXSMO7bHWmUBbVn7TA1UoYIz3lAoOzvE6juadve4aU3goeaBj8PIrhG0M2zEEfKgOL1Al9MSU1GGUmRW9dBofeA4e1cGmlGQrUKnt73n0sHap6","PhotoBase64":null}
这几乎是我所得到的,目前,我在这个应用程序上使用了异步存储,但至少可以存储一个带有“无用”数据的对象,我不确定异步存储是否适合这与否,如果不是,我该怎么办?
编辑:在阅读了更多内容后,我发现我需要第二个 token ,来自 microsoft graph https://massivescale.com/microsoft-v2-endpoint-primer/ 的刷新 token 仍然需要有关如何存储数据并在 token 过期时刷新 token 的帮助,
编辑 2:不幸的是,我没有从 api 获得刷新 token 或 expiresAt 值

最佳答案

我无法帮助该特定身份验证提供程序(从未使用过 Office 365),但这是您需要遵循的一般步骤:

  • 发送请求以获取访问和刷新 token
  • 将 token 存储在通过重新加载/重新启动保留数据的存储中(对于 Web,它将是 localStorage,对于 RN sqlite 或 asyncstorage 或您使用的任何东西)
  • 保存可用于所有组件(Redux、Context API 甚至您自己的解决方案)的 token 和身份验证状态。当用户验证、取消验证或 token 过期时,需要显示/隐藏应用程序的某些部分
  • 您需要以某种方式知道 token 何时过期(无法说明如何操作,但 API 文档应该有一些信息)并使用 setTimeout为了刷新
  • 刷新 token 时,应将其持久化(参见 n.2)并更新全局身份验证状态(参见 n.3)
  • 当应用程序刚刚(重新)启动时,检查您是否在存储中保留了访问/刷新 token (请参阅 n.2)并相应地更新全局身份验证状态(请参阅 n.3)
  • 您的路由应该对身份验证状态更改使用react(请参阅路由库的文档,有关 protected /经过身份验证的路由)。显示敏感内容的组件也应该对身份验证状态更改使用react。

  • 这是我的 Reactjs 身份验证解决方案(不幸的是,没有 RN 示例),它使用 JWT 针对我自己的 API 对客户端进行身份验证。这种情况下的访问 token 也是刷新 token 。我使用一种没有 Redux 的方法,只是纯粹的 React 和 JS。我希望这会对你有所帮助。
    import { useCallback, useState, useEffect } from "react";
    import JWT from "jsonwebtoken";
    import { ENV } from "../config";
    import { useLanguageHeaders } from "./i18n";

    const decodeToken = (token) =>
    typeof token === "string" ? JWT.decode(token) : null;

    //This class is responsible for authentication,
    //refresh and global auth state parts
    //I create only one instance of AuthProvider and export it,
    //so it's kind of singleton
    class AuthProvider {
    //Getter for _authStatus
    get authStatus() {
    return this._authStatus;
    }

    constructor({ tokenEndpoint, refreshEndpoint, refreshLeeway = 60 }) {
    this._tokenEndpoint = tokenEndpoint;
    this._refreshEndpoint = refreshEndpoint;
    this._refreshLeeway = refreshLeeway;
    //When app is loaded, I load token from local storage
    this._loadToken();
    //And start refresh function that checks expiration time each second
    //and updates token if it will be expired in refreshLeeway seconds
    this._maybeRefresh();
    }

    //This method is called in login form
    async authenticate(formData, headers = {}) {
    //Making a request to my API
    const response = await fetch(this._tokenEndpoint, {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    ...headers,
    },
    redirect: "follow",
    body: JSON.stringify(formData),
    });
    const body = await response.json();
    if (response.status === 200) {
    //Authentication successful, persist token and update _authStatus
    this._updateToken(body.token);
    } else {
    //Error happened, replace stored token (if any) with null
    //and update _authStatus
    this._updateToken(null);
    throw new Error(body);
    }
    }

    //This method signs user out by replacing token with null
    unauthenticate() {
    this._updateToken(null);
    }

    //This is needed so components and routes are able to
    //react to changes in _authStatus
    addStatusListener(listener) {
    this._statusListeners.push(listener);
    }

    //Components need to unsubscribe from changes when they unmount
    removeStatusListener(listener) {
    this._statusListeners = this._statusListeners.filter(
    (cb) => cb !== listener
    );
    }

    _storageKey = "jwt";
    _refreshLeeway = 60;
    _tokenEndpoint = "";
    _refreshEndpoint = "";
    _refreshTimer = undefined;
    //This field holds authentication status
    _authStatus = {
    isAuthenticated: null,
    userId: null,
    };
    _statusListeners = [];

    //This method checks if token refresh is needed, performs refresh
    //and calls itself again in a second
    async _maybeRefresh() {
    clearTimeout(this._refreshTimer);

    try {
    const decodedToken = decodeToken(this._token);

    if (decodedToken === null) {
    //no token - no need to refresh
    return;
    }

    //Note that in case of JWT expiration date is built-in in token
    //itself, so I do not need to make requests to check expiration
    //Otherwise you might want to store expiration date in _authStatus
    //and localStorage
    if (
    decodedToken.exp * 1000 - new Date().valueOf() >
    this._refreshLeeway * 1000
    ) {
    //Refresh is not needed yet because token will not expire soon
    return;
    }

    if (decodedToken.exp * 1000 <= new Date().valueOf()) {
    //Somehow we have a token that is already expired
    //Possible when user loads app after long absence
    this._updateToken(null);
    throw new Error("Token is expired");
    }

    //If we are not returned from try block earlier, it means
    //we need to refresh token
    //In my scenario access token itself is used to get new one
    const response = await fetch(this._refreshEndpoint, {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    },
    redirect: "follow",
    body: JSON.stringify({ token: this._token }),
    });
    const body = await response.json();
    if (response.status === 401) {
    //Current token is bad, replace it with null and update _authStatus
    this._updateToken(null);
    throw new Error(body);
    } else if (response.status === 200) {
    //Got new token, replace existing one
    this._updateToken(body.token);
    } else {
    //Network error, maybe? I don't care unless its 401 status code
    throw new Error(body);
    }
    } catch (e) {
    console.log("Something is wrong when trying to refresh token", e);
    } finally {
    //Finally block is executed even if try block has return statements
    //That's why I use it to schedule next refresh try
    this._refreshTimer = setTimeout(this._maybeRefresh.bind(this), 1000);
    }
    }

    //This method persist token and updates _authStatus
    _updateToken(token) {
    this._token = token;
    this._saveCurrentToken();

    try {
    const decodedToken = decodeToken(this._token);

    if (decodedToken === null) {
    //No token
    this._authStatus = {
    ...this._authStatus,
    isAuthenticated: false,
    userId: null,
    };
    } else if (decodedToken.exp * 1000 <= new Date().valueOf()) {
    //Token is expired
    this._authStatus = {
    ...this._authStatus,
    isAuthenticated: false,
    userId: null,
    };
    } else {
    //Token is fine
    this._authStatus = {
    ...this._authStatus,
    isAuthenticated: true,
    userId: decodedToken.id,
    };
    }
    } catch (e) {
    //Token is so bad that can not be decoded (malformed)
    this._token = null;
    this._saveCurrentToken();
    this._authStatus = {
    ...this._authStatus,
    isAuthenticated: false,
    userId: null,
    };
    throw e;
    } finally {
    //Notify subscribers that _authStatus is updated
    this._statusListeners.forEach((listener) => listener(this._authStatus));
    }
    }

    //Load previously persisted token (called in constructor)
    _loadToken() {
    this._updateToken(window.localStorage.getItem(this._storageKey));
    }

    //Persist token
    _saveCurrentToken() {
    if (typeof this._token === "string") {
    window.localStorage.setItem(this._storageKey, this._token);
    } else {
    window.localStorage.removeItem(this._storageKey);
    }
    }
    }

    //Create authProvider instance
    const authProvider = new AuthProvider(ENV.auth);

    //This hook gives a component a function to authenticate user
    export const useAuthenticate = () => {
    const headers = useLanguageHeaders();

    return useCallback(
    async (formData) => {
    await authProvider.authenticate(formData, headers);
    },
    [headers]
    );
    };

    //This hook gives a function to unauthenticate
    export const useUnauthenticate = () => {
    return useCallback(() => authProvider.unauthenticate(), []);
    };

    //This hook allows components to get authentication status
    //and react to changes
    export const useAuthStatus = () => {
    const [authStatus, setAuthStatus] = useState(authProvider.authStatus);

    useEffect(() => {
    authProvider.addStatusListener(setAuthStatus);

    return () => {
    authProvider.removeStatusListener(setAuthStatus);
    };
    }, []);

    return authStatus;
    };
    功能组件内的这行代码可以知道用户是否经过身份验证: const { isAuthenticated } = useAuthStatus();

    关于javascript - 需要帮助尝试在 native react 中刷新我的 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62540603/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com