權限管理模塊

登錄相關

  • 權限管理模塊(基礎版)
    • 模塊設計與實現
    • 優化點:
  • 前后端用戶驗證
    • 實現方式
  • 常見的攻擊手段及防御手段

權限管理模塊(基礎版)

RBAC(Role-Base Access Control,基于角色的訪問控制):是權限管理的常用方案。
核心:通過用戶 - 角色 - 權限的三層關聯,靈活分配和管理權限。并不將用戶和全新啊直接綁定。適合多用戶多權限場景。

模塊設計與實現

以Java + Spring Boot + Spring Security為例

1、實體設計(庫表設計)
需要具備3個實體(用戶、角色、權限),以及2個關系表(用戶-角色、角色-權限)。

// 用戶實體
@Data
public class User {private Long id;private String username;private String password; // 加密存儲(如BCrypt)private Integer status; // 1-啟用,0-禁用// 關聯角色(一對多,通過user_role表)private List<Role> roles;
}// 角色實體
@Data
public class Role {private Long id;private String name; // 角色名稱(如“系統管理員”)private String code; // 角色標識(如“ROLE_ADMIN”,用于Spring Security)// 關聯權限(一對多,通過role_permission表)private List<Permission> permissions;
}// 權限實體
@Data
public class Permission {private Long id;private String name; // 權限名稱(如“刪除用戶”)private String code; // 權限標識(如“user:delete”,用于權限校驗)private Integer type; // 1-菜單,2-按鈕(接口)private String url; // 接口URL(如“/api/user/delete”)private Long parentId; // 父權限ID(用于菜單層級)
}
-- 用戶-角色關聯表
CREATE TABLE `user_role` (`id` bigint NOT NULL AUTO_INCREMENT,`user_id` bigint NOT NULL,`role_id` bigint NOT NULL,PRIMARY KEY (`id`),KEY `idx_user` (`user_id`),KEY `idx_role` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- 角色-權限關聯表
CREATE TABLE `role_permission` (`id` bigint NOT NULL AUTO_INCREMENT,`role_id` bigint NOT NULL,`perm_id` bigint NOT NULL,PRIMARY KEY (`id`),KEY `idx_role` (`role_id`),KEY `idx_perm` (`perm_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2、Mapper層設計,提供數據庫基本操作。

public interface UserMapper {// 查詢用戶User selectByUsername(String username);// 查詢用戶的角色List<Role> selectRolesByUserId(Long userId);// 查詢角色的權限List<Permission> selectPermissionsByRoleId(Long roleId);
}
public Interface RolePermissionMapper() {// CRUD
}

3、Service實現,提供查詢用戶權限,用戶與角色,角色與權限的分配與修改。
用戶登錄時,查詢權限,用于后續權限校驗。

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public List<String> login(String username,String password) {// 校驗邏輯,判斷用戶是否存在return 用戶信息(包含權限列表)}// 根據用戶名查詢用戶及其關聯的角色和權限public User getUserWithRolesAndPermissions(String username) {User user = userMapper.selectByUsername(username);if (user == null) {throw new UsernameNotFoundException("用戶不存在");}// 查詢用戶關聯的角色List<Role> roles = userMapper.selectRolesByUserId(user.getId());// 為每個角色查詢關聯的權限for (Role role : roles) {List<Permission> permissions = userMapper.selectPermissionsByRoleId(role.getId());role.setPermissions(permissions);}user.setRoles(roles);return user;}
}
// 管理用戶-角色 角色-權限
@Service
public class RolePermissionService {@Autowiredprivate RolePermissionMapper rolePermissionMapper;// 給角色分配權限(先刪除舊關聯,再插入新關聯)@Transactionalpublic void assignPermissions(Long roleId, List<Long> permIds) {// 1. 刪除該角色已有的所有權限關聯rolePermissionMapper.deleteByRoleId(roleId);// 2. 插入新的權限關聯if (permIds != null && !permIds.isEmpty()) {List<RolePermission> list = permIds.stream().map(permId -> {RolePermission rp = new RolePermission();rp.setRoleId(roleId);rp.setPermId(permId);return rp;}).collect(Collectors.toList());rolePermissionMapper.batchInsert(list);}}
}

3、權限校驗(限制到接口層面)
結合Spring Security實現接口訪問時單獨權限校驗。
原理:

  • 將用戶權限加載到上下文中。并通過注解或配置文件進行攔截。
  • Spring Security的授權流程通過 http.authorizeRequests() 對web請求進行授權保護。授權決策由 AccessDecisionManager 進行,它會對比當前訪問資源所需的權限信息和用戶信息中的權限信息。

步驟:

  1. 加載用戶到Spring Security:
    實現UserDetailsService,將用戶信息(包含角色和權限)轉換為Security可識別的userDetails。
    UserDetailsService:從數據庫中取出用戶的賬號密碼。
@Service
public class CustomUserDetailsService implements UserDetailsService {@Autowiredprivate UserService userService;// 將用戶信息以及對應的角色,權限交由Security管理@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查詢用戶及其角色、權限User user = userService.getUserWithRolesAndPermissions(username);if (user == null) {throw new UsernameNotFoundException("用戶不存在");}// 提取角色(需加前綴"ROLE_",符合Security規范)List<String> roleCodes = user.getRoles().stream().map(role -> "ROLE_" + role.getCode()).collect(Collectors.toList());// 提取權限標識(如"user:delete")List<String> permCodes = user.getRoles().stream().flatMap(role -> role.getPermissions().stream()).map(Permission::getCode).collect(Collectors.toList());// 合并角色和權限(Security將其統一視為"權限")List<String> authorities = new ArrayList<>();authorities.addAll(roleCodes);authorities.addAll(permCodes);// 返回Security用戶對象。提供參數由Security轉換用戶與權限return org.springframework.security.core.userdetails.User.withUsername(user.getUsername()).password(user.getPassword()).authorities(authorities) // 角色和權限都作為authority.accountLocked(user.getStatus() == 0) // 狀態為0時鎖定.build();}
}
  1. 權限校驗
  • 注解方式校驗:在Controller方法上使用@PerAuthorize注解,指定所需要的權限。
@RestController
@RequestMapping("/api/user")
public class UserController {// 需擁有"user:delete"權限才能訪問@PreAuthorize("hasAuthority('user:delete')")@DeleteMapping("/{id}")public Result deleteUser(@PathVariable Long id) {// 業務邏輯return Result.success();}// 需擁有"ROLE_ADMIN"角色才能訪問@PreAuthorize("hasRole('ADMIN')") // 自動拼接"ROLE_"前綴@GetMapping("/list")public Result getUserList() {// 業務邏輯return Result.success();}
}
  • 配置列中通過URL匹配指定權限:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true) // 開啟@PreAuthorize注解
public class SecurityConfig {@Autowiredprivate CustomUserDetailsService userDetailsService;@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(auth -> auth// 訪問"/api/admin/**"需ADMIN角色.requestMatchers("/api/admin/**").hasRole("ADMIN")// 訪問"/api/user/delete"需"user:delete"權限.requestMatchers("/api/user/delete/**").hasAuthority("user:delete")// 其他接口允許認證用戶訪問.anyRequest().authenticated());return http.build();}
}

4、前端權限適配(動態加載)
根據用戶權限展示菜單和按鈕。
原理:

  • 登陸后,獲取當前用戶權限列表(后端返回)
  • 渲染菜單/按鈕時,只顯示用戶權限內的菜單/按鈕。
// 1. 登錄后獲取用戶權限
async function login(username, password) {const res = await api.login({ username, password });const { permissions } = res.data; // 后端返回的權限列表(如["user:delete", "menu:user"])localStorage.setItem('permissions', JSON.stringify(permissions));
}// 2. 權限判斷工具函數
function hasPermission(permission) {const permissions = JSON.parse(localStorage.getItem('permissions') || '[]');return permissions.includes(permission);
}// 3. 動態渲染按鈕(使用自定義指令)
Vue.directive('perm', {inserted(el, binding) {if (!hasPermission(binding.value)) {el.remove(); // 無權限則移除按鈕}}
});// 4. 在模板中使用
<template><button v-perm="'user:delete'">刪除用戶</button>
</template>

優化點:

  • 角色繼承:支持角色間的父子關系,需要在role表中添加Parent_id字段。
  • 數據權限:在功能權限基礎上,控制數據可見范圍(員工只能查看本人數據)。可通過在權限表中添加data_scope字段(限制全部/本部門/個人),結合SQL攔截器實現。
  • 權限緩存:可以將用戶權限緩存到Redis中(key用戶名,value權限列表),減少數據庫壓力,提高性能。(注意每次修改權限后需要考慮緩存一致性)。

前后端用戶驗證

交互中保證同一用戶的核心:身份標識與驗證機制。通過不同技術保證每次請求來自同一個用戶,防止身份假冒以及會話混亂。

實現方式

1、 Cookie + Session的傳統方案(適用于Web端)
最早且最成熟的方案,依賴服務器的會話存儲和客戶端的Cookie傳遞標識。
核心流程

  • 用戶登錄驗證:
    • 登錄驗證通過后,在服務器內存/數據庫中創建一個session(包含用戶標識登錄狀態等信息),生成唯一的SESSIONID。
    • 后端通過Set-Cookie響應頭返回客戶端,客戶端自動將其保存到Cookie中(通常設置HttpOnly和Secure屬性)。
  • 后續請求身份確認
    • 客戶端每次請求時,瀏覽器自動子啊請求頭中Cookie字段按中攜帶SessionID。
    • 后端通過SessionID查詢服務器的Session數據,若存在且有效(未過期),則任務是同一用戶。

相關配置:

  • HttpOnly: true:禁止 JavaScript 讀取 Cookie,防止 XSS 攻擊竊取SessionID;
  • Secure: true:僅在 HTTPS 協議下傳輸 Cookie,避免明文泄露;
  • SameSite: Strict/Lax:限制 Cookie 跨域發送,防止 CSRF 攻擊;
  • 會話超時機制:如 30 分鐘無操作自動失效,降低SessionID被盜用的風險。

2、基于Token的無狀態方案(適用于多端應用)
Token方案不依賴服務器存儲會話,而是通過加密令牌傳遞用戶信息,更適合前后端分離,移動端、小程序等場景。
核心流程

  • 生成Token:
    • 用戶登陸驗證通過后,后端使用密鑰生成一個加密token(常見為JWT格式),包含用戶Id、過期時間、簽名等信息(不包含敏感數據)。
    • 后端將Token返回給客戶端,客戶端存儲在LocalStorage、SessionStorage或App本地存儲。
  • 攜帶Token請求
    • 客戶端每次請求時,在HTTP請求頭中(如Authorization:Bearer<.token>) 中攜帶token。
    • 后端驗證Token簽名(確保未篡改)和過期時間,解析出用戶Id,確認是同一用戶。
      JWT(JSON Web Token)示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOjEsIm5hbWUiOiJKb2huIiwiZXhwIjoxNzIwMDAwMDAwfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
第一部分:算法聲明(HS256);
第二部分:用戶信息(用戶 ID、過期時間);
第三部分:簽名(用密鑰生成,確保內容未被篡改)。

相關配置

  • 短期有效期:Token 過期時間設為 15-30 分鐘,降低被盜用后的風險;
  • 刷新 Token 機制:同時返回access_token(短期)和refresh_token(長期,如 7 天),過期后用refresh_token重新獲取access_token,避免頻繁登錄;
  • Token 黑名單:用戶登出或密碼修改時,將舊 Token 加入黑名單(Redis 存儲),強制失效。

3、基于設備指紋與生物識別的增強方案(高安全性場景)
在金融、支付等安全性高的場景中,需要結合設備信息或生物特性輔助驗證"同一用戶”。

  • 設備指紋驗證:
    • 后端收集客戶端信息(CPU信息、操作系統等),生成唯一“設備指紋”
    • 登錄時,將用戶ID+設備指紋綁定,后續請求若設備指紋不符(如同一賬號在新設備登錄),觸發二次驗證(如短信驗證)。
  • 生物識別輔助:
    • 移動端App可結合指紋識別,面部識別,通過后才允許攜帶Token請求敏感接口。
    • 即使Token泄露,沒有生物特征同樣無法完成操作。

4、跨域場景下身份有效。
當前后端域名不同,需要配置確保身份標識能跨域傳遞。

  • Cookie跨域:
    • 后端設置Access-Control-Allow-Credentials: true響應頭;
    • 前端請求時攜帶credentials: 'include’參數(如 Axios 配置);
    • Cookie 設置domain: .parent.com(主域名一致時),允許子域名共享。
  • Token跨域
    • 無跨域限制,只在請求投中正確攜帶Token即可(不受Cookie同源策略影響)。

補充
Cookie同源策略:是瀏覽器的一種安全機制,用于防止不同源的網頁之間相互訪問數據,從而保護用戶信息的安全。所謂“同源”,指的是兩個網頁的協議、域名和端口都相同。
作用:
同源策略的主要目的是防止惡意網站竊取用戶數據。例如,如果用戶登錄了一個銀行網站A,然后又訪問了另一個網站B,如果沒有同源策略,網站B可以讀取網站A的Cookie,從而獲取用戶的敏感信息。

常見的攻擊手段及防御手段

針對身份盜用的典型攻擊(XSS、CSRF、重放攻擊等),需要針對性防護。

1、防御XSS攻擊(防止標識被竊取)
XSS攻擊通過注入惡意腳本竊取前端存儲的標識(如LocalStorage中的Token,document.cookie)。
預防:

  • 前端輸入過濾:對用戶輸入內容(評論、表單)進行HTML轉義(如>轉義為& lt/ ); 使用框架自帶的安全渲染(如React的JSX自動轉義,VUE的v-text)。
  • 后端輸出編碼:返回給前端的數據中,對HTML/JS特殊字符編碼,避免直接渲染未處理的用戶輸入。
  • 啟用CSP(內容安全策略):

2、防御CSRF攻擊(防止身份被濫用)
CSRF攻擊:利用用戶已登錄的身份,誘導用戶在第三方網站上發起惡意請求(如轉賬),防護措施:

  • SameSite Cookie:通過SameSite-Strict限制Cookie僅在同域請求中攜帶,徹底阻止跨域CSRF。
  • CSFR Token:對敏感操作(如表單操作、轉賬),后端生成隨機CSFR Token(綁定Session),前端表單攜帶該Token,后端驗證Token的有效性后才處理請求。
    例:前端表單隱藏字段,后端對比 Session 中的 Token。

3、防止重放攻擊(防止標識被重復使用)
攻擊者竊取Token后重復發送請求(如重復下單),防護措施:

  • Token短期有效+刷新時間
    • assess_token(訪問令牌)有效期15~20分鐘,用于日常請求;
    • refresh token(刷新令牌)有效期7天,用于過期后獲取access_token,且刷新時驗證設備信息(如設備信息);
    • 每次刷新后,舊access_token立即失效,refresh_token采用“一次性”機制(使用后立即失效,返回新的refresh_token)。
  • 請求時間戳+nonce
    前端請求時攜帶timestamp(當前時間戳)和nonce(隨機字符串,僅用一次)后端驗證:
    • 時間戳與服務器時間 不差5分鐘(防止過期請求)。
    • nonce在Redis記錄,已使用過的nonce直接拒絕(防止重復請求)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94217.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94217.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94217.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

征服與守護:從拉里·埃里森看八號人格的職場王者之道

真正的強者&#xff0c;從不遵守別人的規則2010年&#xff0c;加利福尼亞州的圣何塞機場迎來了一架不速之客——一架意大利產的馬基戰斗機以一種極其霸道的姿態降落在跑道上。艙蓋打開&#xff0c;走下來的不是空軍飛行員&#xff0c;而是一位身穿飛行員服、戴著墨鏡的企業家&a…

【Linux系統】命名管道與共享內存

前言&#xff1a; 上文我們講到了匿名管道【Linux系統】匿名管道以及進程池的簡單實現-CSDN博客 本文我們來講一講命名管道與共享內存 命名管道 上面我們講到&#xff0c;匿名管道只能用于有血緣關系&#xff08;尤其父子&#xff09;的進程進行通信&#xff01;但如果…

搜索體驗優化:ABP vNext 的查詢改寫(Query Rewrite)與同義詞治理

&#x1f50e; 搜索體驗優化&#xff1a;ABP vNext 的查詢改寫&#xff08;Query Rewrite&#xff09;與同義詞治理 &#x1f4da; 目錄&#x1f50e; 搜索體驗優化&#xff1a;ABP vNext 的查詢改寫&#xff08;Query Rewrite&#xff09;與同義詞治理1. 背景與問題界定 &…

Text2API與Text2SQL深度對比:自然語言驅動的數據交互革命

在數字化浪潮中&#xff0c;如何讓人機交互更加自然流暢&#xff1f;Text2API與Text2SQL技術應運而生&#xff0c;它們如同魔法般將自然語言轉化為機器可執行的指令&#xff0c;讓數據交互不再高不可攀。本文將深入剖析這兩項技術的原理、優劣勢及應用場景&#xff0c;帶您領略…

數據可視化與分析平臺設計與實現案例

數據可視化與分析平臺設計與實現案例(python) 下面分享一個完整的 Flask 數據可視化與分析平臺代碼,包含所有必要的組件和功能。這個平臺允許用戶上傳數據文件、進行基本的數據清洗、生成各種可視化圖表以及查看基礎統計分析結果。 產品設計 核心功能 數據上傳與管理(支…

Kotlin-基礎語法練習二

接上一篇博客 每個 Kotlin 程序都是由兩種部分組成的&#xff1a; 1、表達式&#xff08;Expressions&#xff09;&#xff1a;用于計算值的部分&#xff0c;比如 2 3、函數調用、變量賦值等&#xff0c;它們通常會返回一個結果。2、語句&#xff08;Statements&#xff09;…

與Deepseek對話了解單片機基礎知識

keil5里的c語言編程的程序燒錄到單片機里具體過程是啥&#xff1f;如何能把機器語言轉換為電路控制&#xff1f; 步驟 所在位置 核心工具 輸入->輸出 比喻 1. 編譯 Keil5 (PC) 編譯…

利用背景圖片定位套打檔案封面

某些表單設計起來比較復雜&#xff0c;或只有表單的空白圖片資料。Nhdeep檔案目錄套打工具&#xff08;nhdeep官網www.nhdeep.com&#xff09;支持將已有的表單圖片作為模版背景圖片&#xff0c;然后使用文本框進行精準的位置定位&#xff0c;再進行文本替換。 背景圖片定位套…

微信HOOK 實現自動下載視頻

1、前言 在收發消息的接口中&#xff0c;圖片和文件這類接口是相對容易自動下載&#xff0c;但是視頻的下載是需要手動點擊的&#xff0c;并且只有這一種下載方式&#xff0c;實現自動化也比較困難&#xff0c;一些項目的開發中&#xff0c;需要自動下載收到的視頻并保存&#…

【GPT入門】第57課 詳解 LLamaFactory 與 XTuner 實現大模型多卡分布式訓練的方案與實踐

【GPT入門】第57課 大模型多卡計算1. 理論2.LLamaFacotory實踐3. xtuner3.1 介紹3.1 安裝3.2 xtuner訓練3.4 訓練后格式轉換3.5 合并基礎模型與lora模型3.6 參數說明3.7 訓練過程主觀檢驗1. 理論 deepspeed的三種訓練方式 zero-1&#xff0c;優化器狀態分片。的優勢體現在多卡…

部隊多媒體信息發布系統:賦能 IPTV 與電教化,加速軍營信息化變革

在科技飛速發展的當下&#xff0c;部隊的信息化建設也在不斷推進。多媒體信息發布系統作為一種創新的技術手段&#xff0c;正逐步融入部隊的各個領域&#xff0c;為部隊的現代化建設注入強大動力。?在部隊 IPTV 方面&#xff0c;多媒體信息發布系統展現出卓越的性能。它打破了…

FTP/TCP上傳下載文件

封裝C風格地ftplib為ftp.c和ftp.h文件&#xff1a;cftplient類&#xff08;主要成員變量&#xff1a;文件大小、文件修改時間、主要成員函數&#xff1a;get函數&#xff08;遠程文件名、本地文件名、核對文件時間&#xff09;、put函數&#xff08;本地文件名、服務端文件名、…

DeepSeek V3.1深度解析:一個模型兩種思維,邁向Agent時代的第一步!

名人說&#xff1a;博觀而約取&#xff0c;厚積而薄發。——蘇軾《稼說送張琥》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄一、什么是DeepSeek V3.1&#xff1f;為什么這么火&#x1f680;1. 發布時間線回顧2.…

VsCode 便攜版(綠色版)下載及配置

下載 VsCode 便攜版&#xff0c;并確保所有配置和擴展都保存在一起&#xff0c;實現真正的“綠色版”效果 核心步驟概覽 核心原理是在 VSCode 的主程序目錄下創建一個名為 data 的文件夾&#xff0c;VSCode 啟動時如果檢測到這個文件夾&#xff0c;就會自動切換到便攜模式&am…

使用VLLM部署大模型embedding/chat 的API

模型下載&#xff1a;一般通過modelscope提供的方式進行下載&#xff0c;速度更快&#xff0c;huggingface下模型即便開啟了魔法也還是很慢&#xff0c;對于9B以上的模型都是至少15G的。 比如需要下載qwen3-embedding-8b的模型&#xff0c;可以通過提供的一段代碼自動進行下載到…

Blender模型動畫導入到UE5

UE5支持直接導入FBX文件&#xff0c;但在實際應用中筆者發現&#xff1a;剛開始使用的是UE5.3&#xff0c;在UE5.3中直接將.fbx文件拖入UE中導入后是一個個的零件&#xff0c;后來使用了datasmith插件等其他辦法&#xff0c;怎么都沒有達到想要的效果。后面升級UE5.4以后&#…

Promise詳解:Promise解決ajax回調嵌套問題

目錄 一、Promise是什么 二、回調地獄 三、Promise解決回調地獄的原理 四、promaise實例 一、Promise是什么 1、主要用于異步計算 2、可以將異步操作隊列化&#xff0c;按照期望的順序執行&#xff0c;返回符合預期的結果 4、可以在對象之間傳遞和操作promise&#xff0c…

【Kubernetes知識點】Pod調度和ConfigMaps

目錄 1.如何將特定Pod調度到指定的節點&#xff1f; 2.什么是節點的親和性&#xff1f; 3.什么是污點&#xff0c;它的主要用途是什么&#xff1f; 4.解釋ConfigMap的作用。 5.Secret和ConfigMap相比較有哪些優點。 6.解釋ResourceQuota的作用 1.如何將特定Pod調度到指定…

火車頭使用Post方法采集Ajax頁面教程

前面有寫過一篇瀑布流的采集方法&#xff0c;今天在添加一個POST方法來采集Ajax刷新頁面的教程。 之前的文章請看&#xff1a;火車頭采集動態加載Ajax數據&#xff08;無分頁瀑布流網站&#xff09; 如果遇到POST方法來架子Ajax數據&#xff0c;這和我之前寫的是兩個類型&…