最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于SpringBoot、SpringSecurity、JWT、RBAC搭建一套可落地的權(quán)限系統(tǒng)

 更新時間:2026年05月23日 09:48:24   作者:百錦再@新空間創(chuàng)想科技  
本文詳解釋如何基于SpringBoot、SpringSecurity、JWT、RBAC搭建一套可落地的權(quán)限系統(tǒng),文章指出項目中常見的權(quán)限混亂問題,介紹了JWT在權(quán)限系統(tǒng)中的的角色,以及RBAC模型的優(yōu)勢,闡述了權(quán)限系統(tǒng)需要解決的核心問題,如確認用戶身份、確認用戶權(quán)限、后端接口安全邊界等

前言

在企業(yè)級后臺系統(tǒng)開發(fā)中,登錄認證、接口鑒權(quán)、角色管理、權(quán)限控制幾乎是繞不過去的核心基礎(chǔ)能力。

很多項目初期只是簡單做了一個登錄接口,等業(yè)務逐漸復雜之后,就會暴露出一系列問題:

  • 前端菜單能隱藏,但后端接口并沒有真正做權(quán)限控制
  • 角色和權(quán)限混用,導致后續(xù)擴展困難
  • 接口命名混亂,權(quán)限點設(shè)計失控
  • 前端和后端權(quán)限規(guī)則不一致
  • JWT 只是“登錄態(tài)載體”,沒有真正和權(quán)限體系打通

這篇文章就從實際項目角度出發(fā),基于 Spring Boot + Spring Security + JWT + RBAC,帶你完整搭建一套可落地的權(quán)限系統(tǒng)。

本文主要覆蓋以下內(nèi)容:

  • 什么是 RBAC,為什么它適合后臺管理系統(tǒng)
  • JWT 在權(quán)限系統(tǒng)中的角色
  • Spring Security 如何接入 JWT
  • 如何實現(xiàn)接口級權(quán)限控制
  • 前后端權(quán)限協(xié)同如何設(shè)計
  • 權(quán)限系統(tǒng)常見坑點與擴展方向

一、權(quán)限系統(tǒng)為什么容易越做越亂

權(quán)限系統(tǒng)做亂,往往不是因為不會寫代碼,而是從建模開始就有問題。

常見錯誤主要有以下幾類。

1. 角色和權(quán)限混為一談

比如代碼里直接寫死:

  • 管理員可以新增用戶
  • 普通用戶只能查看自己的信息
  • 審核員可以審批訂單

一開始角色少的時候還能勉強維護,但隨著角色越來越多,代碼里會充滿各種 if else,后續(xù)每新增一個角色,業(yè)務判斷都會繼續(xù)膨脹。

2. 只做前端權(quán)限,不做后端權(quán)限

很多項目把“權(quán)限控制”理解成:

  • 菜單隱藏
  • 按鈕隱藏
  • 頁面不可見

這只能改善交互體驗,不能形成真正的安全邊界。只要知道接口地址,攻擊者或者越權(quán)用戶依然可能直接發(fā)請求訪問接口。

3. 權(quán)限粒度設(shè)計不清晰

有的系統(tǒng)權(quán)限點是中文,有的是 URL,有的是動作名,最后會變成這種情況:

  • user:add
  • user_save
  • /sys/user/create
  • 新增用戶

這種混亂命名一旦出現(xiàn),權(quán)限表、代碼注解、前端判斷就會越來越難維護。

4. 登錄認證和權(quán)限授權(quán)耦合嚴重

很多項目登錄后返回一堆角色類型,后端再根據(jù)角色做硬編碼判斷,前端也根據(jù)角色做頁面渲染。角色變更一次,就要同時改多個地方。

5. JWT 用了,但沒有打通權(quán)限模型

很多系統(tǒng)確實使用了 JWT,但只是為了無狀態(tài)登錄。登錄成功之后,token 里只有用戶 ID,接口校驗也只是“是否登錄”,并沒有真正校驗當前用戶是否具備某項權(quán)限。

所以權(quán)限系統(tǒng)的關(guān)鍵,不是用了什么框架,而是是否把“認證”和“授權(quán)”分開設(shè)計,并且是否真正落實到了后端接口層。

二、權(quán)限系統(tǒng)要解決的核心問題

權(quán)限系統(tǒng)的目標不是“用戶能登錄”,而是要真正解決下面幾個問題。

1. 確認當前用戶是誰

也就是認證,Authentication。

用戶通過用戶名密碼、短信驗證碼、第三方登錄等方式登錄之后,系統(tǒng)需要確認身份。

2. 確認當前用戶能做什么

也就是授權(quán),Authorization。

登錄成功只代表身份合法,不代表可以訪問所有頁面、所有菜單和所有接口。

3. 接口必須有真正的安全邊界

菜單隱藏不是權(quán)限控制的終點,真正的邊界一定是后端接口。

4. 支持后續(xù)角色和權(quán)限擴展

一個小系統(tǒng)可能一開始只有管理員和普通用戶,但后面可能會擴展出:

  • 部門管理員
  • 運營人員
  • 審核專員
  • 咨詢師
  • 租戶管理員

如果模型一開始設(shè)計得過于簡單,后期擴展成本會非常高。

5. 前后端規(guī)則要一致

后端負責最終權(quán)限校驗,前端負責菜單、按鈕、頁面的動態(tài)控制,兩者必須基于同一套權(quán)限點設(shè)計。

三、為什么大多數(shù)后臺系統(tǒng)都適合用 RBAC

RBAC 的全稱是 Role-Based Access Control,也就是基于角色的訪問控制。

它最核心的關(guān)系鏈是:

用戶 -> 角色 -> 權(quán)限

這種模型的好處很明顯:

  • 用戶不直接綁定大量權(quán)限
  • 角色作為中間層,方便統(tǒng)一管理
  • 權(quán)限變更時只需要調(diào)整角色與權(quán)限關(guān)系,不必逐個修改用戶

舉個簡單例子。

系統(tǒng)里有三個角色:

  • 系統(tǒng)管理員
  • 咨詢師
  • 普通用戶

系統(tǒng)管理員擁有全部權(quán)限;
咨詢師可以查看用戶信息、管理咨詢記錄;
普通用戶只能查看自己的資料和訂單。

如果沒有角色層,就需要給每個用戶單獨分配權(quán)限,維護成本會迅速失控。

RBAC 的價值就在于把“用戶”和“能力”解耦了。

四、權(quán)限點應該怎么設(shè)計

權(quán)限點設(shè)計建議采用統(tǒng)一命名規(guī)則:

模塊:資源:動作

例如:

sys:user:view
sys:user:create
sys:user:update
sys:user:delete
sys:role:view
sys:role:assign
order:refund:approve

這樣設(shè)計有幾個明顯優(yōu)勢。

1. 語義清晰

看到權(quán)限碼就能知道它控制的是什么能力。

2. 前后端都能共用

前端按鈕、菜單、路由守衛(wèi)和后端 @PreAuthorize 可以使用同一套權(quán)限碼。

3. 適合數(shù)據(jù)庫持久化

權(quán)限表里直接維護 permission_code,便于檢索、比對和擴展。

4. 便于接口級權(quán)限控制

Spring Security 中可以直接寫:

@PreAuthorize("hasAuthority('sys:user:view')")

這里要強調(diào)一個原則:

不要把 URL 當權(quán)限碼,也不要把中文文案當權(quán)限碼。

權(quán)限碼應該是穩(wěn)定、統(tǒng)一、可維護的系統(tǒng)內(nèi)部標識。

五、JWT 在權(quán)限系統(tǒng)中的作用

JWT 本質(zhì)上是一種令牌機制,用來在前后端之間傳遞登錄態(tài)。

一個典型的 JWT 包括三部分:

  • Header
  • Payload
  • Signature

在權(quán)限系統(tǒng)中,JWT 主要承擔的是“認證憑證”的角色,而不是權(quán)限系統(tǒng)本身。

JWT 的典型使用流程如下:

  1. 用戶提交用戶名和密碼登錄
  2. 后端驗證通過后生成 JWT
  3. 前端保存 token
  4. 后續(xù)請求在請求頭中攜帶:
Authorization: Bearer xxx
  1. 后端通過過濾器解析 token,確認當前用戶身份
  2. 結(jié)合權(quán)限信息完成授權(quán)判斷

JWT 的優(yōu)勢:

  • 無狀態(tài),適合前后端分離
  • 適合 Web、App、小程序統(tǒng)一接入
  • 易于和網(wǎng)關(guān)、微服務體系整合

但 JWT 也有明顯問題:

  • token 一旦簽發(fā),不容易立即失效
  • 如果把太多權(quán)限直接塞到 token 中,會帶來權(quán)限變更延遲問題
  • 需要配合黑名單、短期 token、刷新機制做增強

因此,JWT 只是權(quán)限體系中的一環(huán),而不是全部。

六、Spring Boot + JWT + Spring Security 的整體實現(xiàn)流程

一個完整的權(quán)限系統(tǒng)實現(xiàn)流程一般如下:

第一步:用戶登錄

前端調(diào)用登錄接口,提交用戶名和密碼。

第二步:服務端校驗身份

后端校驗用戶名密碼是否正確。

第三步:查詢用戶角色和權(quán)限

根據(jù)當前用戶查出其角色集合和權(quán)限集合。

第四步:簽發(fā) JWT

后端把用戶身份信息和必要權(quán)限信息寫入 token,返回給前端。

第五步:前端保存 token

后續(xù)請求統(tǒng)一通過請求頭攜帶 token。

第六步:后端過濾器解析 token

JWT 過濾器提取用戶名、權(quán)限,并構(gòu)造 Spring Security 的認證上下文。

第七步:接口做權(quán)限校驗

Controller 層通過 @PreAuthorize 校驗權(quán)限,決定能否執(zhí)行接口。

這套流程里,最關(guān)鍵的是兩部分:

  • JWT 過濾器
  • 接口級權(quán)限控制

七、權(quán)限系統(tǒng)的數(shù)據(jù)模型怎么設(shè)計

最基礎(chǔ)的 RBAC 表設(shè)計通常包括下面幾張表:

1. 用戶表sys_user

保存用戶名、密碼、昵稱、狀態(tài)、創(chuàng)建時間等基礎(chǔ)信息。

2. 角色表sys_role

保存角色編碼、角色名稱、狀態(tài)等信息。

3. 權(quán)限表sys_permission

保存權(quán)限編碼、權(quán)限名稱、類型等。

4. 用戶角色關(guān)聯(lián)表sys_user_role

描述用戶和角色之間的多對多關(guān)系。

5. 角色權(quán)限關(guān)聯(lián)表sys_role_permission

描述角色和權(quán)限之間的多對多關(guān)系。

如果還需要控制菜單,可以繼續(xù)增加菜單表:

6. 菜單表sys_menu

菜單項可關(guān)聯(lián) permission_code,前端根據(jù)權(quán)限動態(tài)渲染。

注意一點:

菜單不是權(quán)限,菜單只是權(quán)限的展示入口。

真正的權(quán)限控制最終還是要落到接口上。

八、登錄接口設(shè)計

登錄接口的請求參數(shù)一般比較簡單:

public record LoginRequest(String username, String password) {
}

返回值建議包含三類信息:

  • token
  • 當前用戶基礎(chǔ)信息
  • 當前用戶權(quán)限集合

例如:

public record LoginResponse(
        String token,
        UserInfo user,
        Set<String> permissions
) {
    public record UserInfo(Long id, String username, String nickname, Set<String> roles) {
    }
}

登錄服務邏輯示例:

@Service
public class AuthService {

    private final UserService userService;
    private final PasswordEncoder passwordEncoder;
    private final JwtTokenProvider jwtTokenProvider;

    public LoginResponse login(LoginRequest request) {
        User user = userService.findByUsername(request.username())
                .orElseThrow(() -> new IllegalArgumentException("用戶名或密碼錯誤"));

        if (!passwordEncoder.matches(request.password(), user.getPassword())) {
            throw new IllegalArgumentException("用戶名或密碼錯誤");
        }

        Set<String> permissions = userService.getPermissions(user.getId());
        String token = jwtTokenProvider.generateToken(user.getUsername(), permissions);

        return new LoginResponse(
                token,
                new LoginResponse.UserInfo(user.getId(), user.getUsername(), user.getNickname(), user.getRoles()),
                permissions
        );
    }
}

登錄接口設(shè)計要點

  • 密碼必須加密存儲,通常使用 BCrypt
  • 登錄失敗提示不要過于具體,避免賬號枚舉風險
  • 登錄成功后盡量一次性返回前端所需核心信息,減少額外請求

九、JWT 工具類實現(xiàn)

JWT 工具類主要負責三件事:

  • 生成 token
  • 解析 token
  • 校驗 token

示例代碼如下:

@Component
public class JwtTokenProvider {

    private final SecretKey secretKey;
    private final long expiration;

    public JwtTokenProvider(@Value("${security.jwt.secret}") String secret,
                            @Value("${security.jwt.expiration}") long expiration) {
        this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        this.expiration = expiration;
    }

    public String generateToken(String username, Set<String> permissions) {
        Date now = new Date();
        Date expireTime = new Date(now.getTime() + expiration);

        return Jwts.builder()
                .subject(username)
                .claim("permissions", permissions)
                .issuedAt(now)
                .expiration(expireTime)
                .signWith(secretKey)
                .compact();
    }

    public Claims parseToken(String token) {
        return Jwts.parser()
                .verifyWith(secretKey)
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    public String getUsername(String token) {
        return parseToken(token).getSubject();
    }

    public List<String> getPermissions(String token) {
        return parseToken(token).get("permissions", List.class);
    }
}

實際項目中的注意點

  • JWT 密鑰不能太短
  • 密鑰不能直接硬編碼在代碼中
  • token 有效期不建議過長
  • 高安全場景應增加刷新 token 或黑名單機制

十、JWT 過濾器接入 Spring Security

為了讓 Spring Security 知道當前請求對應的是哪個用戶,需要在請求進入 Controller 之前先經(jīng)過 JWT 過濾器。

示例代碼如下:

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwtTokenProvider;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String header = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (header != null && header.startsWith("Bearer ")) {
            String token = header.substring(7);

            try {
                String username = jwtTokenProvider.getUsername(token);
                List<String> permissions = jwtTokenProvider.getPermissions(token);

                List<GrantedAuthority> authorities = permissions.stream()
                        .map(SimpleGrantedAuthority::new)
                        .toList();

                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(username, null, authorities);

                SecurityContextHolder.getContext().setAuthentication(authentication);
            } catch (Exception ignored) {
            }
        }

        filterChain.doFilter(request, response);
    }
}

這個過濾器的本質(zhì)就是:

  • 把請求頭中的 token 解析出來
  • 把 token 中的用戶信息和權(quán)限信息轉(zhuǎn)成 Spring Security 可識別的認證對象
  • 放進 SecurityContext

后續(xù)接口層的權(quán)限校驗就能基于這個上下文進行。

十一、Spring Security 配置

核心配置通常包括以下幾件事:

  • 關(guān)閉 CSRF
  • 配置無狀態(tài) Session
  • 放行登錄接口和 Swagger
  • 所有其他接口默認要求認證
  • 注冊 JWT 過濾器
  • 開啟方法級權(quán)限控制

示例代碼如下:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .sessionManagement(session ->
                        session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/auth/login", "/swagger-ui/**", "/v3/api-docs/**").permitAll()
                        .anyRequest().authenticated()
                )
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

這里的核心原則是:

登錄接口放行,其他接口默認先要求登錄,再在具體接口方法上細分權(quán)限。

十二、接口級權(quán)限控制為什么推薦@PreAuthorize

相比把所有權(quán)限規(guī)則都堆在過濾器里,把權(quán)限寫在接口方法上更清晰、更可維護。

示例:

@PreAuthorize("hasAuthority('sys:user:view')")
@GetMapping("/api/users")
public ApiResponse<List<UserResponse>> list() {
    return ApiResponse.ok(userService.findAll());
}

再比如新增用戶:

@PreAuthorize("hasAuthority('sys:user:create')")
@PostMapping("/api/users")
public ApiResponse<UserResponse> create(@RequestBody @Valid UserRequest request) {
    return ApiResponse.ok(userService.create(request));
}

這種方式的優(yōu)點很明確:

  • 權(quán)限要求和業(yè)務接口天然綁定
  • 容易讀懂
  • 容易審查
  • 粒度足夠細
  • 支持復雜表達式

例如:

@PreAuthorize("hasAuthority('sys:role:view') or hasAuthority('sys:menu:view')")

十三、RESTful 用戶管理接口設(shè)計

用戶管理接口建議遵循 RESTful 風格設(shè)計:

  • GET /api/users 查詢用戶列表
  • GET /api/users/{id} 查詢用戶詳情
  • POST /api/users 新增用戶
  • PUT /api/users/{id} 更新用戶
  • DELETE /api/users/{id} 刪除用戶
  • GET /api/users/me 查詢當前登錄用戶信息

示例代碼如下:

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PreAuthorize("hasAuthority('sys:user:view')")
    @GetMapping
    public ApiResponse<List<UserResponse>> list() {
        return ApiResponse.ok(userService.findAll());
    }

    @PreAuthorize("hasAuthority('sys:user:view')")
    @GetMapping("/{id}")
    public ApiResponse<UserResponse> detail(@PathVariable Long id) {
        return ApiResponse.ok(userService.findById(id));
    }

    @PreAuthorize("hasAuthority('sys:user:create')")
    @PostMapping
    public ApiResponse<UserResponse> create(@RequestBody @Valid UserRequest request) {
        return ApiResponse.ok(userService.create(request));
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @PutMapping("/{id}")
    public ApiResponse<UserResponse> update(@PathVariable Long id,
                                            @RequestBody @Valid UserRequest request) {
        return ApiResponse.ok(userService.update(id, request));
    }

    @PreAuthorize("hasAuthority('sys:user:delete')")
    @DeleteMapping("/{id}")
    public ApiResponse<Void> delete(@PathVariable Long id) {
        userService.delete(id);
        return ApiResponse.ok(null);
    }
}

不要把接口寫成:

  • /getUserList
  • /saveUser
  • /deleteUserById

這種動作式路徑不利于規(guī)范統(tǒng)一,也不利于接口文檔維護。

十四、統(tǒng)一返回結(jié)構(gòu)的必要性

很多項目會對返回值做統(tǒng)一包裝,例如:

public record ApiResponse<T>(boolean success, String message, T data) {
    public static <T> ApiResponse<T> ok(T data) {
        return new ApiResponse<>(true, "success", data);
    }

    public static <T> ApiResponse<T> fail(String message) {
        return new ApiResponse<>(false, message, null);
    }
}

它的優(yōu)點是:

  • 前端統(tǒng)一處理
  • 錯誤提示風格一致
  • 易于后續(xù)擴展錯誤碼、traceId、分頁信息

但也要注意:

統(tǒng)一返回結(jié)構(gòu)不等于可以忽略 HTTP 狀態(tài)碼。

例如:

  • 參數(shù)錯誤返回 400
  • 未登錄返回 401
  • 無權(quán)限返回 403
  • 服務異常返回 500

HTTP 狀態(tài)碼和業(yè)務響應體應該一起使用,而不是互相替代。

十五、Swagger 為什么應該盡早接入

權(quán)限系統(tǒng)類項目接口很多,調(diào)試頻率也很高,所以 Swagger 文檔很有必要。

優(yōu)勢主要有三個:

  • 便于前后端聯(lián)調(diào)
  • 便于測試人員驗證接口
  • 便于后期維護和交接

Spring Boot 中可以使用 springdoc-openapi,配置完成后訪問:

/swagger-ui.html

即可查看接口文檔。

如果接口需要 Bearer Token,還可以在 OpenAPI 中配置安全方案,讓 Swagger 頁面直接支持攜帶 token 測試受保護接口。

十六、前后端權(quán)限協(xié)同怎么做

前端和后端的職責一定要分清楚:

后端職責

  • 登錄認證
  • 接口鑒權(quán)
  • 權(quán)限邊界兜底

前端職責

  • 菜單動態(tài)渲染
  • 按鈕動態(tài)顯示
  • 路由守衛(wèi)
  • 提升用戶體驗

一個典型做法是:

登錄成功后,后端返回:

  • token
  • 用戶信息
  • 權(quán)限集合

然后前端再調(diào)用一個權(quán)限元數(shù)據(jù)接口,例如:

GET /api/permissions/meta

返回:

  • 當前角色
  • 權(quán)限集合
  • 菜單配置

前端根據(jù)權(quán)限集合判斷:

  • 哪些菜單顯示
  • 哪些按鈕顯示
  • 哪些路由允許訪問

但需要再次強調(diào):

前端的權(quán)限判斷只能改善體驗,真正的安全校驗必須由后端完成。

十七、權(quán)限系統(tǒng)常見坑點

這一部分是最容易踩坑的地方。

1. 只做菜單權(quán)限,不做接口權(quán)限

這不是權(quán)限系統(tǒng),只是 UI 隱藏。

2. 把角色判斷寫死在業(yè)務代碼里

例如:

if ("admin".equals(role)) {
    ...
}

這種方式在角色擴展后會迅速失控。

3. 權(quán)限碼不統(tǒng)一

同一個系統(tǒng)里混用多種命名風格,后續(xù)維護會非常痛苦。

4. 把全部權(quán)限都塞進 JWT

權(quán)限一旦變更,舊 token 中的權(quán)限快照可能仍然有效。

5. 沒有 token 失效策略

比如用戶被禁用、修改密碼、角色調(diào)整后,舊 token 依然可用。

6. 沒有區(qū)分功能權(quán)限和數(shù)據(jù)權(quán)限

能訪問用戶列表,不代表能訪問所有用戶數(shù)據(jù)。

十八、數(shù)據(jù)權(quán)限怎么擴展

當系統(tǒng)除了控制“功能能不能訪問”,還要控制“數(shù)據(jù)能不能看到”時,就進入了數(shù)據(jù)權(quán)限層。

典型數(shù)據(jù)范圍包括:

  • 僅本人數(shù)據(jù)
  • 本部門數(shù)據(jù)
  • 本部門及子部門數(shù)據(jù)
  • 全部數(shù)據(jù)
  • 自定義數(shù)據(jù)范圍

實現(xiàn)方式一般有兩類:

1. 在 Service 層加過濾條件

例如只能查當前用戶自己創(chuàng)建的數(shù)據(jù):

creator_id = currentUserId

2. 在持久層統(tǒng)一注入數(shù)據(jù)范圍條件

例如 MyBatis 攔截器、SQL 拼接等。

這里要明確一點:

接口權(quán)限和數(shù)據(jù)權(quán)限不是一回事。

你可能有權(quán)限訪問某個接口,但返回數(shù)據(jù)范圍仍然需要繼續(xù)過濾。

十九、JWT 失效與刷新策略

JWT 常見的兩個問題是:

  • 權(quán)限變更后舊 token 如何處理
  • token 過期后如何續(xù)簽

一個較成熟的方案是雙 token:

  • access token:短期有效
  • refresh token:長期有效

access token 用于訪問接口,refresh token 用于換發(fā)新 token。

如果系統(tǒng)規(guī)模不大,也可以先做簡化版:

  • access token 有效期 2 小時
  • 重新登錄獲取新 token
  • 配合賬號狀態(tài)校驗
  • 必要時加入 token 黑名單或 token 版本號機制

核心不是一步做到最復雜,而是設(shè)計上要預留升級空間。

二十、權(quán)限系統(tǒng)為什么需要審計日志

權(quán)限系統(tǒng)如果沒有審計能力,后期排查問題會非常被動。

建議至少記錄以下行為:

  • 登錄成功和失敗
  • 登出
  • 用戶創(chuàng)建、修改、刪除
  • 角色分配
  • 權(quán)限變更
  • 高危接口調(diào)用
  • 審批、退款、導出等關(guān)鍵操作

審計日志建議包含:

  • 操作人
  • 操作時間
  • 請求 IP
  • 請求參數(shù)
  • 操作資源
  • 操作結(jié)果
  • 變更前后內(nèi)容
  • traceId

一旦出現(xiàn)越權(quán)、誤刪、誤授權(quán),這些信息就是最直接的排查依據(jù)。

二十一、一個建議的落地路徑

如果你要從零搭建權(quán)限系統(tǒng),建議按階段推進。

第一階段:最小可用版

  • 用戶登錄
  • JWT 鑒權(quán)
  • 接口級 @PreAuthorize
  • 基礎(chǔ)角色和權(quán)限表
  • 前端菜單和按鈕控制

第二階段:管理能力補齊

  • 用戶管理
  • 角色管理
  • 權(quán)限管理
  • 菜單管理
  • Swagger 文檔

第三階段:安全增強

  • token 刷新
  • 登錄失敗限制
  • 用戶禁用
  • token 黑名單
  • 密碼策略

第四階段:復雜場景擴展

  • 數(shù)據(jù)權(quán)限
  • 多租戶
  • 單點登錄
  • 審計日志
  • 網(wǎng)關(guān)統(tǒng)一鑒權(quán)

這樣做的好處是每一階段都可以形成明確交付,而不是一開始就做成一個難以落地的大系統(tǒng)。

總結(jié)

權(quán)限系統(tǒng)是后臺項目中非?;A(chǔ)、但也非常容易被做偏的一部分。

真正可落地的權(quán)限系統(tǒng),至少要滿足下面幾個原則:

  • 認證和授權(quán)分開設(shè)計
  • 前端權(quán)限只負責展示控制
  • 后端接口權(quán)限才是真正邊界
  • 角色只是組織方式,權(quán)限才是能力邊界
  • 權(quán)限點命名必須統(tǒng)一
  • 后續(xù)必須考慮數(shù)據(jù)權(quán)限、審計和 token 失效機制

從工程實踐角度看,Spring Boot + Spring Security + JWT + RBAC 是一套足夠成熟且穩(wěn)定的方案。只要權(quán)限模型清晰、接口層保護到位、前后端協(xié)同一致,這套方案完全可以支撐大多數(shù)企業(yè)后臺系統(tǒng)。

參考代碼片段匯總

登錄接口權(quán)限流程

@PostMapping("/api/auth/login")
public ApiResponse<LoginResponse> login(@RequestBody LoginRequest request) {
    return ApiResponse.ok(authService.login(request));
}

接口級權(quán)限控制

@PreAuthorize("hasAuthority('sys:user:view')")
@GetMapping("/api/users")
public ApiResponse<List<UserResponse>> list() {
    return ApiResponse.ok(userService.findAll());
}

JWT 過濾器

String header = request.getHeader(HttpHeaders.AUTHORIZATION);
if (header != null && header.startsWith("Bearer ")) {
    String token = header.substring(7);
}

 

到此這篇關(guān)于基于SpringBoot、SpringSecurity、JWT、RBAC搭建一套可落地的權(quán)限系統(tǒng)的文章就介紹到這了,更多相關(guān)Spring Boot + JWT + RBAC 權(quán)限系統(tǒng)實戰(zhàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于springboot打包目錄全解析

    關(guān)于springboot打包目錄全解析

    這篇文章主要介紹了springboot打包目錄解析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Spring Boot + Kotlin整合MyBatis的方法教程

    Spring Boot + Kotlin整合MyBatis的方法教程

    前幾天由于工作需要,便開始學習了kotlin,java基礎(chǔ)扎實學起來也還算比較快,對于kotlin這個編程語言自然是比java有趣一些,下面這篇文章主要給大家介紹了關(guān)于Spring Boot + Kotlin整合MyBatis的方法教程,需要的朋友可以參考下。
    2018-01-01
  • java 常用快捷鍵匯總(超經(jīng)典)

    java 常用快捷鍵匯總(超經(jīng)典)

    以下是對在java開發(fā)中的常用快捷鍵進行了匯總介紹。非常全哦!需要的朋友可以過來參考下
    2013-08-08
  • CentOS8.2安裝Java 14.0.2的教程詳解

    CentOS8.2安裝Java 14.0.2的教程詳解

    這篇文章主要介紹了CentOS8.2安裝Java 14.0.2的詳細教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • SpringBoot集成Redis及SpringCache緩存管理示例詳解

    SpringBoot集成Redis及SpringCache緩存管理示例詳解

    本文介紹了如何在SpringBoot中集成Redis并使用SpringCache進行緩存管理,詳解了Redis的配置、使用以及SpringCache的注解,還闡述了SpringCache的工作原理,包括其AOP實現(xiàn)和與各種緩存框架的集成,使得開發(fā)者可以輕松實現(xiàn)緩存功能,以提高應用性能
    2024-09-09
  • Spring?控制反轉(zhuǎn)和依賴注入的具體使用

    Spring?控制反轉(zhuǎn)和依賴注入的具體使用

    本文主要介紹了Spring?控制反轉(zhuǎn)和依賴注入,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 解決@Validated注解無效,嵌套對象屬性的@NotBlank無效問題

    解決@Validated注解無效,嵌套對象屬性的@NotBlank無效問題

    這篇文章主要介紹了解決@Validated注解無效,嵌套對象屬性的@NotBlank無效問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • ShardingProxy讀寫分離之原理、配置與實踐過程

    ShardingProxy讀寫分離之原理、配置與實踐過程

    ShardingProxy是Apache?ShardingSphere的數(shù)據(jù)庫中間件,通過三層架構(gòu)實現(xiàn)讀寫分離,解決高并發(fā)場景下數(shù)據(jù)庫性能瓶頸,其核心功能包括SQL路由、負載均衡、數(shù)據(jù)一致性保障和故障轉(zhuǎn)移,支持主從架構(gòu)下的透明分庫分表及讀寫分流,廣泛應用于微服務和高流量業(yè)務系統(tǒng)
    2025-08-08
  • Java并發(fā)編程示例(一):線程的創(chuàng)建和執(zhí)行

    Java并發(fā)編程示例(一):線程的創(chuàng)建和執(zhí)行

    這篇文章主要介紹了Java并發(fā)編程示例(一):線程的創(chuàng)建和執(zhí)行,本文是系列文章的第一篇,需要的朋友可以參考下
    2014-12-12
  • SpringBoot中使用Redis作為全局鎖示例過程

    SpringBoot中使用Redis作為全局鎖示例過程

    這篇文章主要為大家介紹了SpringBoot中使用Redis作為全局鎖示例過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03

最新評論

灵石县| 鄂托克旗| 昌黎县| 林口县| 阿巴嘎旗| 许昌县| 张家川| 正镶白旗| 商水县| 磐石市| 泰顺县| 饶河县| 五台县| 兴山县| 买车| 尚义县| 忻城县| 哈尔滨市| 柘荣县| 清苑县| 驻马店市| 高陵县| 尉氏县| 玉溪市| 铁岭县| 将乐县| 宜君县| 东乡族自治县| 手机| 周至县| 洛扎县| 岳普湖县| 唐河县| 襄城县| 汉寿县| 长岭县| 宁国市| 古丈县| 沂水县| 茌平县| 东平县|