我一直在使用
aws-amplify
库和 ionic,想知道如何检查用户是否登录?我有 Firebase 背景,所以这是完全不同的。这样我就可以根据用户的登录状态授予对某些页面的访问权限。在我的 auth
提供商中,我导入 Amplify {Auth}
。我可以看到可以获取几条数据,但我不知道该使用什么。有 currentUserPoolUser
、getCurrentUser()
、getSyncedUser()
、currentAuthenticatedUser
、currentSession
、getCurrentUser()
、userSession
、currentUserCredentials
、currentCredentials
和 currentUserInfo
。我似乎也找不到任何有关这方面的文档。我读过和看过的所有内容都会被掩盖,直到用户登录......这一切都应该在客户端上完成吗?谢谢。
我在每个页面中使用 ionViewCanEnter() 函数来允许/拒绝访问。该函数的返回值决定页面是否可以加载(并且在运行构造函数之前执行)。在这个函数中,你必须实现你的逻辑。
就我而言,使用 Amplify,我正在这样做:
async function ionViewCanEnter() {
try {
await Auth.currentAuthenticatedUser();
return true;
} catch {
return false;
}
}
由于 amplify currentAuthenticatedUser() 返回一个承诺,我使用异步等待来等待响应以了解用户是否已登录。
嘿我想现在你只能使用
Auth.currentUserInfo();
来检测是否登录。如果您尚未登录,它将返回 undefined
;如果您已登录,它将返回 object
。
这可以使用 Auth 的 fetchAuthSession() 方法来实现。
final CognitoAuthSession res = await Amplify.Auth.fetchAuthSession();
if (res.isSignedIn) {
// do your thang
}
您可以通过监听集线器将其设为自定义挂钩(上述答案中的 ionViewCanEnter 用于启动应用程序):
挂钩tsx:
import {useState, useEffect} from 'react';
import {Hub, Auth} from 'aws-amplify';
export default function AuthenticatedStatus(): Boolean {
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
async function ionViewCanEnter() {
console.log('hey');
try {
const authenticatedUser = await Auth.currentAuthenticatedUser();
if (authenticatedUser !== undefined) {
setIsAuthenticated(true);
} else {
setIsAuthenticated(false);
}
} catch {
setIsAuthenticated(false);
}
}
useEffect(() => {
ionViewCanEnter();
});
useEffect(() => {
const listener = data => {
switch (data.payload.event) {
case 'signIn' || 'autoSignIn' || 'tokenRefresh':
console.log('is authenticated');
setIsAuthenticated(true);
break;
case 'signOut' || 'signIn_failure' || 'tokenRefresh_failure' || 'autoSignIn_failure':
console.log('is not authenticated');
setIsAuthenticated(false);
break;
}
};
Hub.listen('auth', listener);
});
return isAuthenticated;
}
使用方法:
const isAuthenticated = AuthenticatedStatus();
如果您将 Angular 与 ionic 结合使用,那么您可以在身份验证器服务中执行类似的操作
import {AmplifyService} from 'aws-amplify-angular';
...
constructor(private amplifyService:AmplifyService)
{
this.amplifyService.authStateChange$.subscribe(auth => {
switch (auth.state) {
case 'signedIn':
this.signedIn = true;
case 'signedOut':
this.signedIn = false;
break;
default:
this.signedIn = false;
}
}
}
然后您可以在路由器中使用
this.signedIn
和 canActivate
防护。
Angular 路由器防护:https://angular.io/guide/router#preventing-unauthorized-access
一个与我一起工作的例子,小心流量控制,两者 事件循环风格和异步/等待风格:
import { Auth } from "aws-amplify";
...
exampleIsLoggedIn() {
const notLoggedInStringThrown = "The user is not authenticated";
Auth.currentAuthenticatedUser().then(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(_currentAuthenticatedUser) => {
this.$log.debug("Yes, user is logged in.");
},
(error) => {
if (error === notLoggedInStringThrown) {
this.$log.debug("No, user is not yet logged in.");
} else {
this.$log.error(error);
}
}
);
},
async exampleIsLoggedInAsync() {
const notLoggedInStringThrown = "The user is not authenticated";
try {
/* currentAuthenticatedUser = */ await Auth.currentAuthenticatedUser();
this.$log.debug("Yes, user is logged in.");
} catch (error) {
if (error === notLoggedInStringThrown) {
this.$log.debug("No, user is not yet logged in.");
} else {
this.$log.error(error);
}
}
},
import { Auth } from 'aws-amplify';
Auth.currentAuthenticatedUser({
// Optional, By default is false. If set to true,
// this call will send a request to Cognito to get the latest user data
bypassCache: false
})
.then((user) => console.log(user))
.catch((err) => console.log(err));
此方法可用于在页面加载时检查用户是否登录。如果没有用户登录,则会抛出错误。该方法应在配置 Auth 模块或用户登录后调用。以确保您可以监听 auth 事件
configured
或 signIn
。
来源:https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/#retrieve-current-authenticated-user
我写了一个很好地满足我的目的的钩子:
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Auth, Hub } from "aws-amplify";
export interface UserDetailsT {
username: string,
email: string,
emailVerified: boolean,
};
const useAuth = (): [UserDetailsT | null, Dispatch<SetStateAction<UserDetailsT | null>>] => {
const [userDetails, setUserDetails] = useState<UserDetailsT | null>(null);
useEffect(() => {
const getUserDetails = async () => {
try {
if (userDetails === null) {
const { username, attributes } = await Auth.currentAuthenticatedUser() || null;
setUserDetails({
username,
email: attributes?.email,
emailVerified: attributes?.email_verified
});
}
} catch {
setUserDetails(null);
}
}
getUserDetails();
Hub.listen('auth', () => getUserDetails());
}, [Auth, userDetails, setUserDetails]);
return [userDetails, setUserDetails];
};
export default useAuth;
我通过在 Amplify 的
Authenticator
组件中更新的全局上下文解决了这个问题。
最终结果如下所示:
import { AuthenticatedDataContext } from '../amplify/AuthenticatedDataContext';
const MyComponent = () => {
const { data: auth } = React.useContext(AuthenticatedDataContext);
return <>{auth.isAuthenticated ? `You are logged in as ${JSON.stringify(auth.user)}` : 'You are logged out'}</>
};
实现如下。
import * as React from 'react';
export const AuthenticatedDataContext = React.createContext();
const initData = () => ({
user: undefined,
isAuthenticated: false,
});
export const AuthenticatedData = (props) => {
const { children } = props;
const [cache, setCache] = React.useState({
keys: new Set(),
data: initData(),
});
const register = (key, user) => {
return setCache((prevCache) => {
const keys = new Set(prevCache.keys);
keys.add(key);
const data = {user, isAuthenticated: !!user};
return {keys, data};
});
};
const unregister = (key) => {
return setCache((prevCache) => {
if (prevCache.keys.has(key)) {
const keys = new Set(prevCache.keys);
keys.delete(key);
const data = (keys.size === 0) ? initData() : prevCache.data;
return {keys, data};
} else {
console.error(`AuthenticatedData.unregister: key of '${key}' does not exist`);
return prevCache;
}
});
};
return (
<AuthenticatedDataContext.Provider value={{data: cache.data, register, unregister}}>
{children}
</AuthenticatedDataContext.Provider>
);
};
import * as React from 'react';
import { Authenticator } from '@aws-amplify/ui-react';
import { AuthenticatedDataContext } from '../amplify/AuthenticatedDataContext';
const UserLifecycle = (props) => {
const { children, componentId, user } = props;
const authenticatedDataContext = React.useRef(
React.useContext(AuthenticatedDataContext)
);
React.useEffect(() => {
const { register, unregister } = authenticatedDataContext.current;
register(componentId, user);
return () => unregister(componentId);
}, [componentId, user]);
return children;
};
export const Login = (props) => {
const { children } = props;
const componentId = React.useId();
return (
<Authenticator>
{({ signOut, user }) => (
<UserLifecycle componentId={componentId} user={user}>
{children}
</UserLifecycle>
)}
</Authenticator>
);
};
// Use Login component anywhere you want to require authentication
// For example:
const MyPrivateComponent = () => {
return (
<Login>
<>Secret stuff</>
</Login>
);
};