问题描述
我没有登录页面,这是 sso 调用
i don't have an login page , this is sso call
在应用程序组件中,我已经调度了一个动作来加载服务器端令牌调用并获取令牌,并根据用户角色我可以在路由中激活守卫.如果守卫激活返回true,我会去仪表板页面.
In the app component, I have dispatched an action to load the server-side token call and get the token and based on the user roles I can activate the guard in routing. if guard activates return true, I will go the dashboard page.
在dashboard页面中,我在浏览器URL中刷新,可以在登录动作效果之前激活执行,因此可以激活返回false并且页面显示为空白.
In the dashboard page, I have a refresh in the browser URL, can activate execute before the login action effects, therefore can activate return false and page displays blank.
仪表盘里有子路由,也有一些子链接,比如产品仪表板/产品,也有激活的守卫,但可以在登录调度动作影响成功调用之前激活返回false.
In the dashboard have child routes, there also have some child links like productsdashboard/products, there also have activated guard, but can activate return false before the login dispatch action effects success call.
有人能帮我做错什么吗?
Can anyone help me what I am doing wrong?
这里是路由,
{
path: '',
component: HomeComponent,
canActivate:[AuthGuard],
children: [
{
path: 'product',
loadChildren: () => productModule
},
{
path: 'order',
loadChildren: () => orderModule
}
]
},
这里是激活方法:在这里,我从效果调用中获得成功,同时从 app.component 分派动作:
here is activate method:here i get the success from effects call while dispatch an action from app.component:
canActivate(): Observable<boolean> {
return this.store.select(appState => appState.auth.isAuthenticated)
.pipe(map(authUser => {
if (!authUser) {
return authUser;
}
return authUser;
}))
}
应用程序组件:
ngOnInit(){
this.onSubmit();
}
onSubmit(): void {
const payload = {
email: '[email protected]',
password: 'admin'
};
alert('dispatch an action');
this.store.dispatch(new LogIn(payload));
}
问题只出现在页面刷新上.单击路由器链接时,逻辑工作正常.
the problem only in a page refresh. when clicking on the router link, the logic works fine.
我的初始状态:
export const initialState: State = {
isAuthenticating:false,
isAuthenticated: false,
user: null,
errorMessage: null
};
流程截图:
推荐答案
我可能有解决方案.
基本上你可以在你的初始状态设置一个属性来表明你正在初始化:
Basically you can set a property in your initial state to indicate that you're initializing:
export interface State {
isAuthenticated: boolean;
isInitializing: boolean;
}
const initialState: State = {
isAuthenticated: false,
isInitializing: true
}
并且当您发送登录或注销时,请确保在 reducer 中将 isInitializing 设置为 false:
And when you dispatch a login or logout, make sure to set isInitializing to false in the reducer:
const _authReducer = createReducer(
initialState,
on(AuthActions.setAuthenticated, (state, action) => ({
...state,
isAuthenticated: true,
isInitializing: false,
})),
on(AuthActions.setUnauthenticated, (state, action) => ({
...state,
isAuthenticated: false,
isInitializing: false,
}))
);
在您的守卫中,您可以使用过滤器等待 isInitializing 设置为 false,然后再返回有关用户身份验证的信息:
In your guard, you can then use a filter to wait for isInitializing to be set to false, before returning information about the user authentication:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
console.log('Authguard running...');
return this.store.select('auth').pipe(
map(authState => authState.isInitializing),
// tap((isInit) => {
// console.log('isInit: ' + isInit);
// }),
filter((isInit) => !isInit),
switchMap(() => {
return this.store.select('auth').pipe(
map(authState => authState.isAuthenticated)
// tap((isAuth) => {
// console.log('isAuth: ' + isAuth);
// }),
map((isAuth) => {
if (isAuth) return isAuth;
return this.router.createUrlTree(['/auth']);
})
);
})
);
}
如果您想在控制台中监控这些值,您可以从 Tap 运算符中删除注释:)
You can remove the comments from the tap operators if you want to monitor these values in the console :)
我使用这个解决方案是为了能够在登录时重新加载特定的 url.如果您在未登录时尝试访问同一页面,您将被重定向到登录.
I'm using this solution to be able to reload on a specific url when logged in. If you try to visit that same page when not logged in you are redirected to the login.
这篇关于在页面刷新中:ngrx store dispatch issue with guard canactivate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!