因为后端访问控制的经验比较丰富,所以这里只记录了前端访问控制的实现。请注意,前端最多只能做到显示控制!并不能保证安全,所以后端是一定要做访问控制的!
基于角色的访问控制需要做到两个层面的访问控制:
控制页面路由的跳转,没有权限的用户不能跳转到指定url
页面元素的显示控制,没有对应权限的用户不能看到该元素
但在此之前,我们还有一项重要的事要做。
存储用户信息
首先我们要做的,并不是和访问控制有关的事,首先我们要保存好用户信息。包括用户的基本信息,如用户名、真实姓名;以及用户角色。下面是数据结构:
user = {
username:"",
realname:"",
role:""
}
存储的时候就将整个user存储,但存在哪里呢?考虑到必须在任何页面都可以访问到,第一反应是存储到rootScope中,但我们应该尽量避免使用rootScope;除此之外,我们可以存储在顶级的controller或者是全局的constant中,这两种解决方案都可以,但它们的问题就是一旦页面刷新,就不管用了($rootScope也一样)。考虑到user这个变量的生命周期应该要与session相同,所以,我使用了SessionStorage。
在创建controller时,需要加入$sessionStorage:
app.controller('controller',['$sessionStorage', function($sessionStorage){}]);
在登录成功后,将user存储到SessionStorage中:
$sessionStorage.USER = user;
好了,之后通过$sessionStorage就可以获取到用户信息了。
user = $sessionStorage.USER;
控制页面路由的跳转
下面我们开始实现第一点:控制页面路由的跳转。
要做到第一点比较容易,Angular路由改变时会触发$stateChangeStart事件(我用的是stateProvider,所以监听stateChangeStart,如果是用的route或是location,应该监听它们对应的事件),监听此事件,在里面根据访问的url以及用户角色进行权限判断,比如登录的判断就可以在里面做,访问那个url需要登录就直接跳转到登录界面。
首先先写一个auth服务,用于权限认证:
/** * 基于角色的访问控制 */ App.service("auth", ["$http","$sessionStorage", function($http, $sessionStorage){ var roles = []; // 从后端数据库获取的角色表 // 从后端获取的角色权限Url映射表,结构为{"role":["/page1", "/page2"……]} var urlPermissions = {}; // 去后端获取 (function(){ // 此处为测试方便,直接赋值了,下面也仅以示例为目的,尽量简单了 roles = ["admin", "user"] urlPermissions = { // 管理员可以访问所用页面 "admin":["*"], // 普通用户可以访问page路径下的所有界面(登录、注册等页面)以及系统主页 "user":["page.*", "app.index", "app.detail"] } })(); function convertState(state) { return state.replace(".", "\\\.").replace("*", ".*"); } return { // 是否有访问某url的权限 isAccessUrl:function(url) { var user = $sessionStorage.USER; for(var role in roles) { if(user.role.toLowerCase() == roles[role].toLowerCase()) { console.log(urlPermissions[roles[role]]) for(i in urlPermissions[roles[role]]) { var regx = eval("/"+convertState(urlPermissions[roles[role]][i])+"/"); console.log(regx+ " "+ url) if(regx.test(url)) { return true; } } } } return false; } } }])
roles是角色,从后台获取;urlPermissions是每个角色对应的能被其访问的url列表,也从后台获取,可通过后台配置。这样,每次新增角色,我们就可以动态为其配置访问权限。
最重要的是isAccessUrl方法,传入url后,isAccessUrl首先会通过$sessionStorage获取用户信息,取得用户角色,然后看用户角色是否在角色表中;若在角色表中,就看此角色是否有访问url的权限。我们在后台配置的时候,是直接指定状态,但如果没有通配符的话,那么每一个页面都得写一个url,所以,就增加了通配符 功能,然后将url列表中的每个url转化为正则表达式,再来验证,这样配置就灵活了很多。
最后是在run中监听事件$stateChangeStart :
App.run(["$rootScope",'$state', "auth", "$sessionStorage", function($rootScope, $state, auth, $sessionStorage){ $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { // 路由访问控制 if(toState.name!="page.login" && !auth.isAccessUrl(toState.name)) { // 查看是否需要登录: var user = $sessionStorage.USER; if(user == null) { event.preventDefault(); $state.go("page.login"); return; } event.preventDefault(); $state.go("page.error"); } }); }])
好了,现在就实现了url的访问控制。
页面元素的显示控制
至于第二点,我的解决方案是自定义指令,下面是示例:
<div zg-access="TEST_ACCESS"></div>
注意,这里传入的不是角色,而是权限。因为用户角色是可以动态扩展的,如果这里写的是什么样的角色才可以访问这个元素,那以后每新增一个角色都将是一个很大很大的麻烦,因为你得一个个来修改代码。下面是自定义指令zg-access的代码:
/** * 元素级别的访问控制指令 */ App.directive("zgAccess", function($sessionStorage, $http){ var roles = []; // 角色 var elemPermissions = {}; // 角色元素权限映射表,如{ "role":{"SEARCH"}},role有这个搜索权限 // 后台获取 (function(){ // 简便起见,这里直接生成 roles = ["admin", "user", "visitor"]; elemPermission = { "admin":["*"], "user":["SEARCH"], "visitor":[] } })(); console.log("zg-access"); return { restrict: 'A', compile: function(element, attr) { // 初始为不可见状态none,还有 禁用disbaled和可用ok,共三种状态 var level = "none"; console.log(attr) if(attr && attr["zgAccessLevel"]) { level = attr["zgAccessLevel"]; } switch(level) { case "none": element.hide(); break; case "disabled": element.attr("disabled", ""); break; } // 获取元素权限 var access = attr["zgAccess"]; // 将此权限上传到后端的数据库 (function(){ //upload })(); return function(scope, element) { // 判断用户有无权限 var user = $sessionStorage.USER; if(user==null||angular.equals({}, user)) { user = {}; user.role = "visitor"; } var role = user.role.toLowerCase(); console.log(roles); for(var i in roles) { var tmp = roles[i].toLowerCase(); if(role == tmp) { tmp = elemPermission[role]; console.log(tmp) for(var j in tmp){ console.log(tmp[j]+" "+access); if(access.toLowerCase() == tmp[j].toLowerCase()) { element.removeAttr("disabled"); element.show(); } } } } }; } } })
zgAccessLevel是一个属性,用来控制级别,如果是none(默认为none),就不显示元素;如果是disbaled,就是元素不可用(如Button不可用)。
下面是元素示例:
<button ng-click="" zg-access="SEARCH" zg-access-level="disabled">Search</button>
此时,若以admin角色或者user角色登录,Search按钮将不可用。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Dreamweaver Mac版
視覺化網頁開發工具