我是AngularJS的新手,我对如何在以下场景中使用angular-“ui-router”感到困惑:
我正在构建一个由两部分组成的Web应用程序 . 第一部分是具有登录和注册视图的主页,第二部分是仪表板(成功登录后) .
我为主页部分创建了一个 index.html
,其角度应用程序和 ui-router
config用于处理 /login
和 /signup
视图,还有另一个文件 dashboard.html
用于仪表板部分及其app和 ui-router
config用于处理许多子视图 .
现在我完成了仪表板部分,不知道如何将这两个部分与不同的角度应用程序结合起来 . 我怎么能告诉家庭应用程序重定向到仪表板应用程序?
10 回答
Use $http Interceptor
通过使用$ http拦截器,您可以将标头发送到后端,或者反过来以这种方式进行检查 .
关于$http interceptors的精彩文章
例:
把它放在你的.config或.run函数中 .
我有另一个解决方案:当您只有登录时要显示的内容时,该解决方案可以正常工作 . 定义一条规则,用于检查您是否已登录,而不是白名单路径的路径 .
在我的例子中,我问我是否没有登录,我想要路由的当前路由不是“/ login”的一部分,因为我的白名单路由如下
所以我可以即时访问这两条路线,如果您在线,将检查每条其他路线 .
这是我的登录模块的整个路由文件
() => { /* code */ }
是ES6语法,改为使用function() { /* code */ }
以下是我们如何摆脱无限路由循环并仍然使用
$state.go
而不是$location.path
我正在制作一个更好的演示以及将一些这些服务清理成一个可用的模块,但这就是我想出来的 . 这是一个解决一些警告的复杂过程,所以请坚持下去 . 你需要把它分成几块 .
Take a look at this plunk .
首先,您需要一项服务来存储用户的身份 . 我称之为
principal
. 可以检查用户是否登录,并且根据请求,它可以解析表示用户身份的基本信息的对象 . 这可以是您需要的任何内容,但必需品将是显示名称,用户名,可能是电子邮件以及用户所属的角色(如果这适用于您的应用) . 校长还有进行角色检查的方法 .其次,您需要一项服务来检查用户想要访问的状态,确保他们已登录(如果需要;不需要登录,密码重置等),然后进行角色检查(如果您的应用程序)需要这个) . 如果未经过身份验证,请将其发送到登录页面 . 如果对它们进行了身份验证,但未通过角色检查,则将其发送到拒绝访问的页面 . 我叫这个服务
authorization
.现在你需要做的就是收听
ui-router
的$stateChangeStart . 这使您有机会检查当前状态,他们想要进入的状态,以及插入授权检查 . 如果失败,您可以取消路由转换,或更改为其他路由 .关于跟踪已经过身份验证的用户's identity is looking it up if you' ve的棘手部分(例如,您在上一个会话之后访问该页面,并在cookie中保存了一个身份验证令牌,或者您可能已经刷新了一个页面,或者从链接中删除了一个URL) ) . 由于
ui-router
的工作方式,您需要在身份验证之前执行一次身份解析 . 您可以使用状态配置中的resolve
选项执行此操作 . 我有一个父状态用于所有状态继承的站点,这会强制在其他任何事情发生之前解析主体 .这里还有另一个问题...
resolve
只被调用一次 . 一旦您的身份查找承诺完成,它就不会再次运行resolve delegate . 因此,我们必须在两个地方进行身份验证:一次是根据您的身份承诺解决resolve
,这涵盖您的应用首次加载,一次在$stateChangeStart
,如果分辨率已经完成,这涵盖了您在任何时候导航状态 .好的,到目前为止我们做了什么?
如果用户已登录,我们会检查应用加载的时间 .
我们跟踪有关登录用户的信息 .
我们将它们重定向到需要用户登录的状态的登录状态 .
如果他们没有访问权限,我们会将其重定向到访问被拒绝状态 .
我们有一种机制可以将用户重定向到他们请求的原始状态,如果我们需要他们登录的话 .
我们可以签署用户(需要与管理您的授权凭证的任何客户端或服务器代码一起连接) .
每次重新加载浏览器或放入链接时,我们都不需要将用户发回登录页面 .
我们从哪里开始?好吧,您可以将州组织到需要登录的区域 . 您可以通过将
data
与roles
添加到这些状态(或者如果您要使用继承,则为父级)来要求经过身份验证/授权的用户 . 在这里,我们将资源限制为管理员:现在,您可以控制用户可以访问路由的状态 . 还有其他问题吗?也许只根据他们是否登录而改变视图的一部分?没问题 . 使用
principal.isAuthenticated()
甚至principal.isInRole()
可以通过多种方式有条件地显示模板或元素 .首先,将
principal
注入控制器或其他任何东西,并将其粘贴到示波器上,以便您可以在视图中轻松使用它:显示或隐藏元素:
等等,等等 . 无论如何,在您的示例应用程序中,您将拥有一个允许未经身份验证的用户访问的主页状态 . 他们可以链接到登录或注册状态,或者将这些表单内置到该页面中 . 无论什么适合你 .
仪表板页面都可以从需要用户登录的状态继承,例如,成为
User
角色成员 . 我们讨论过的所有授权资料都会从那里流出来 .我创建了这个模块来帮助制作这个过程
你可以这样做:
或者也
这是全新的但值得一试!
https://github.com/Narzerus/angular-permission
在我看来,到目前为止发布的解决方案是不必要的复杂 . 有一种更简单的方法 . documentation of ui-router说听
$locationChangeSuccess
并使用$urlRouter.sync()
检查状态转换,暂停或恢复它 . 但即使这样实际上也行不通 .但是,这里有两个简单的替代方案 . 选一个:
解决方案1:监听$ locationChangeSuccess
你可以听
$locationChangeSuccess
,你可以执行一些逻辑,甚至是那里的异步逻辑 . 基于该逻辑,您可以让函数返回undefined,这将导致状态转换正常继续,或者如果用户需要进行身份验证,您可以执行$state.go('logInPage')
. 这是一个例子:请记住,这实际上并不会阻止加载目标状态,但如果用户未经授权,它会重定向到登录页面 . 这没关系,因为无论如何真正的保护在服务器上 .
解决方案2:使用状态解析
在此解决方案中,您使用ui-router resolve feature .
如果用户未经过身份验证,您基本上拒绝
resolve
中的承诺,然后将其重定向到登录页面 .这是怎么回事:
与第一种解决方案不同,此解决方案实际上可以防止目标状态加载 .
首先,您需要一个可以注入到控制器中的服务,该服务对应用程序身份验证状态有所了解 . 使用本地存储保留auth详细信息是一种很好的方法 .
接下来,您需要在状态更改之前检查auth的状态 . 由于您的应用程序有一些需要进行身份验证的页面而其他页面没有进行身份验证,因此请创建一个检查身份验证的父路由,并使所有其他需要该页面的页面成为该父项的子项 .
最后,您需要一些方法来判断您当前登录的用户是否可以执行某些操作 . 这可以通过在您的身份验证服务中添加“can”功能来实现 . 可以采用两个参数: - action - required - (即'manage_dashboards'或'create_new_dashboard') - object - 可选 - 正在操作的对象 . 例如,如果您有仪表板对象,则可能需要检查dashboard.ownerId是否=== loggedInUser.id . (当然,永远不应该信任从客户端传递的信息,并且在将其写入数据库之前,应始终在服务器上对此进行验证) .
免责声明:上面的代码是伪代码,不保证
我想与ui路由器1.0.0.X共享另一个解决方案
您可能知道,现在不推荐使用stateChangeStart和stateChangeSuccess . https://github.com/angular-ui/ui-router/issues/2655
相反,你应该使用$ transitions http://angular-ui.github.io/ui-router/1.0.0-alpha.1/interfaces/transition.ihookregistry.html
这就是我实现它的方式:
首先,我有 AuthService 和一些有用的功能
然后我有这个配置:
你可以看到我使用的
标记只有经过身份验证才可访问的状态 .
然后,在 .run 上,我使用转换来检查验证状态
我使用$ transitions文档中的一些代码构建了这个示例 . 我对ui路由器很新,但它有效 .
希望它可以帮助任何人 .
最简单的解决方案是在未对用户进行身份验证时使用
$stateChangeStart
和event.preventDefault()
来取消状态更改,并将其重定向到作为登录页面的 auth 状态 .我认为您需要
service
来处理身份验证过程(及其存储) .在这项服务中,您需要一些基本方法:
isAuthenticated()
login()
logout()
等......
应该在每个模块的控制器中注入此服务:
在仪表板部分中,使用此服务检查用户是否已通过身份验证(
service.isAuthenticated()
方法) . 如果没有,重定向到/ login在您的登录部分,只需使用表单数据通过
service.login()
方法对用户进行身份验证这个行为的一个好的和强大的例子是项目angular-app,特别是它的security module,它基于令人敬畏的HTTP Auth Interceptor Module
希望这可以帮助