前端实现登录、登出、请求数据的一些思路整理

前端实现登录、登出、请求数据的一些思路整理(基于React、JWT技术)

登录、登出和数据请求是两种不同的数据交互方式,是互相独立的。
  • 登录、登出基于 JWT(JSON WEB TOKEN) 技术,通过请求后台的登录接口,由服务器生成一个 token 凭证返回给前台;前台拿到 token 之后存储到本地的 localStorage 里面,每次进行数据请求的时候都带上 token 传给后台,由后台决定根据 token 返回不同的数据和状态。
根据以上思路整理出前端代码
  • ① 登录和登出

    // 获取当前项目的请求前缀
    const BaseAPI = process.env.REACT_APP_API;
    // 定义本地 token 的键
    const localStorageKey = '__auth_provider_key__';
    // 定义获取本地 token 的方法
    export const getToken = () => window.localStorage.getItem(localStorageKey);
    // 定义清除本地 token 的方法
    export const removeToken = () => window.localStorage.removeItem(localStorageKey);
    // 定义登录方法(核心)
    export const login = (data: { username: string, password: string }) => {
    	return fetch(`${BaseAPI}/login`, {
    		method: 'POST',
    		headers: {
    			'Content-Type': 'application/json'
    		},
    		body: JSON.stringify(data)
    	}).then(async response => {
    		if(response.ok){
    			const result = response.json();
    			window.localStorag.setItem(result.token || '');
    			return result;
    		}else{
    			return Promise.reject(data);
    		}
    	})
    } 
    
  • ② 将 user 的数据和状态共享为全局数据

    // 创建一个 context 对象
    interface User {
    	id: string;
    	name: string;
    	token: string;
    }
    
    interface AuthForm {
    	username: string;
    	password: string;
    }
    
    const AuthContext = React.createContext<{
    	user: User | null,
    	loginMethod: (form: AuthForm) => Promise<void>,
    	logoutMethod: () => Promise<void>
    } || undefined>(undefined);
    AuthContext.displayName = 'AuthContext';
    
    // 创建一个 provider,将数据传递给消费组件进行共享
    export const AuthProvider = () => {
    	const [user, setUser] = useState<User | null>(null);
    	const loginMethod = (form: AuthForm) => login(form).then(setUser);
    	const logoutMethod = () => logout().then(setUser(null));
    	return <AuthContext.Provider value={{user, loginMethod, logoutMethod}} />
    
    }	 
    // 由 app 组件作为消费组件,全局共享 user 信息
    <AuthProvider>
    	<App></App>
    </AuthProvider>
    // 额外封装一个 hooks,用于在消费组件下面的任意地方获取 AuthContext 的数据
    export const useAuth = () => {
    	const context = React.useContext(AuthContext);
    	if(!context){
    		throw new Error("useAuth 必须在 AuthProvide 中使用")
    	}else{
    		return context;
    	}
    }
    
  • ③ 封装请求数据的 hooks

    // 封装请求方法
    import qs from 'qs';
    
    interface Config extends RequestInit {
    	data?: object;
    	token?: string;
    }
    
    export const http = async (endPoint: string, {data, token, ...customConfig}: Config = {}) => {
    	const config = {
    		method: 'GET',
    		headers: {
    			Authorization: token ? `Bearer ${token}` : '',
    			'Content-Type': data ? 'application/json' : ''
    		},
    		...customConfig
    	};
    	if(config.method.toUpperCase() === 'GET'){
    		endPoint += data ? `${qs.stringify(data)}`: '';
    	}else{
    		config.body = JSON.stringify(data || {});
    	}
    	
    	return window.fetch(`${BaseAPI}/${endPoint}`, config).then(async response => {
    		if(response.status == 401){
    			await logout();
    			return Promise.reject({message: '认证过期,请重新登录'})
    		}
    		const data = await response.json();
    		if(response.ok){
    			return data
    		}else{
    			return Promise.reject(data);
    		}
    	})
    }
    // 根据 user 的数据,封装数据请求 hooks
    export const useHttp = () => {
    	const { user } = useAuth();
    	return (...[endPoint, config]: Parameters<typeof http>) => http(endPoint, {...config, token: user?.token});
    }
    // 使用
    const httpRequest = useHttp();
    httpRequest("lists").then(setLists);
    
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值