现在的网站中所有敏感操作都应要求用户经过身份验证(也就是说识别他们是谁)并获得授权(具有足够的权限来执行该操作)。如果 Web 路由无法检查用户身份,那么攻击者将能够访问敏感资源。
JavaScript 框架通常使用路由库来更新浏览器 URL 和页面内容以响应用户操作。在允许用户访问敏感路由之前,各位师傅们应该检查用户是否已通过身份验证,举例。
Angular 中的路由通常通过以下方式完成AppRoutingModule:
@NgModule({
imports: [RouterModule.forRoot([
// These paths are available to all users.
{ path: '', component: HomeComponent },
{ path: 'features', component: FeaturesComponent },
{ path: 'login', component: LoginComponent },
// These routes are only available to users after logging in.
{ path: 'feed', component: FeedComponent, canActivate: [ AuthGuard ]},
{ path: 'profile', component: ProfileComponent, canActivate: [ AuthGuard ]},
// This is the fall-through component when the route is not recognized.
{ path: '**', component: PageNotFoundComponent}
])],
exports: [RouterModule]
})
export class AppRoutingModule {}
React 中的路由通常使用react-router库完成
function Routes(props) {
return (
<Router>
<Switch>
<!-- These routes are publicly available. -->
<Route path="/login">
<Login/>
</Route>
<Route path="/news">
<News/>
</Route>
<Route path="/about">
<About/>
</Route>
<!-- These routes are only available to authenticated user. -->
<AuthenticatedRoute path="/feed" loggedIn={props.loggedIn}>
<Feed/>
</AuthenticatedRoute>
<AuthenticatedRoute path="/profile" loggedIn={props.loggedIn}>
<Profile/>
</AuthenticatedRoute>
<Route path="*">
<NotFound/>
</Route>
</Switch>
</Router>
)
}
/**
* A wrapper for <Route> that redirects to the login screen if the user is not yet authenticated.
*/
function AuthenticatedRoute(props) {
if (props.loggedIn) {
return <Route {...props} />
}
return <Redirect to={{ pathname: `/login` }} />
}
但是,客户端的授权检查可能会被攻击者覆盖,因此在将数据加载到应用程序时检查用户是否登录非常重要。这些授权检查必须在服务器端代码中执行,并且客户端代码应该处理身份验证失败
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<true | UrlTree> {
// Check the user is logged in, redirect them to the login screen if they are not.
return this.authService.isLoggedIn().pipe(
map(isLoggedIn => {
if (!isLoggedIn) {
return this.router.parseUrl('/login')
}
return true
})
);
}
}
export class AuthService {
constructor(private http: HttpClient) {}
// Whether the user is currently logged in.
loggedIn: boolean | null = null
// The user object.
user: User | null = null
// Check whether the user is logged in.
isLoggedIn(): Observable<boolean> {
return this.getCurrentUser().pipe(map(user => {
return user != null
}))
}
// Get the user definition from local state, or the server (if this is the first time we are checking).
getCurrentUser(): Observable<User | null> {
if (this.loggedIn !== null) {
return of(this.user)
}
return this.http.get<User>('/api/auth', {
responseType: 'json'
}).pipe(
tap({
next: user => {
// If we get a user definition from the server it indicates this user is logged in.
this.user = user
this.loggedIn = true
},
error: error => {
// A 401 response from the server indicates this user is not logged in.
this.user = null
this.loggedIn = false
}
}),
catchError(() => {
return of(null)
})
)
}
}
export interface User {
username: string;
}
原文地址:https://fendou.gqr5.cn/1467.htmlclass Feed extends React.Component { constructor(props) { super(props) this.state = { loading : true, posts : [], error : null } } async componentDidMount() { // Load the data for this component. const response = await fetch('/api/feed') const data = await response.json() if (response.ok && data.success) { // Set the data in the component state. this.setState({ loading : false, posts : data.posts }) } else { // Shown an error message if the feed cannot be loaded - for instance, // if the user is not authenticated. this.setState({ loading : false, error : data.error || 'There was a problem loading your feed.' }) } } render() { const error = this.state.error ? <div className="error">{this.state.error}</div> : null let body if (this.state.loading) { body = <div className="loading">Loading...</div> } else { // Render the component based on the data returned from the server. body = this.state.posts.map(post => { return <Post post={post}/> }) } return ( <div> {error} {body} </div> ) } }
感谢您的来访,获取更多精彩文章请收藏本站。
© 版权声明
THE END
暂无评论内容