国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

靈活!Spring Boot 自定義注解結合參數解析器實現權限控制

開發 前端
在實際項目中,該方案適用于對性能和靈活性要求較高的場景,開發者可以在此基礎上,結合自身業務需求,進一步優化和擴展,如 動態權限配置、RBAC(基于角色的訪問控制) 等。

在現代 Web 應用開發中,權限控制是至關重要的一個環節,尤其是在微服務架構和前后端分離的模式下。如何在保證安全性的同時,兼顧開發的便捷性和代碼的可讀性,是開發者需要重點關注的問題。

Spring Boot 提供了多種方式來實現權限管理,例如 Spring Security,但在某些場景下,我們希望有更輕量級、靈活的權限控制方案。本篇文章將介紹如何通過 Spring Boot 3.4 中的 自定義注解 結合 AOP 和 參數解析器,實現一套可擴展的權限控制方案。

本方案的核心思路是:

  1. 通過 AOP 攔截 
    需要權限校驗的方法,實現全局權限校驗邏輯。
  2. 通過攔截器(Interceptor) 
    解析請求 Token,并將用戶信息存儲到上下文中,方便后續權限校驗使用。
  3. 使用自定義參數解析器(HandlerMethodArgumentResolver) 
    在 Controller 方法參數中,通過注解直接獲取當前登錄用戶信息,提高代碼的可讀性。
  4. 支持 SpEL(Spring 表達式語言) 
    以動態方式獲取用戶數據,實現更靈活的權限控制。

本文將結合代碼示例,詳細介紹該方案的實現方式,并最終構建一套完整的權限校驗框架。

自定義注解

獲取當前用戶信息的注解

package com.icoderoad.auth;


import java.lang.annotation.*;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface AuthUser {
    /** 通過 SpEL 表達式從當前登錄用戶信息中提取數據 */
    String value() default "";
}

權限控制注解

package com.icoderoad.auth;


import java.lang.annotation.*;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreAuthorize {
    /** 需要的權限 */
    String[] value() default {};


    /** 權限校驗邏輯(全部匹配或部分匹配) */
    Logical logic() default Logical.AND;


    enum Logical {
        AND, OR;
    }
}

核心組件實現

生成 Token 的工具類

package com.icoderoad.utils;


import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


import java.util.*;
import java.util.function.Function;


@Component
public class JwtUtil {
    @Value("${jwt.secret}")
    private String secret;


    @Value("${jwt.expiration}")
    private Long expiration;


    private final ObjectMapper objectMapper;


    public JwtUtil(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }


    /** 生成 JWT 令牌 */
    public String generateToken(User user) {
        try {
            String payload = objectMapper.writeValueAsString(user);
            return createToken(payload);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


    private String createToken(String payload) {
        return Jwts.builder()
            .claim("info", payload)
            .subject("auth_token")
            .issuedAt(new Date())
            .expiration(new Date(System.currentTimeMillis() + expiration * 1000))
            .signWith(Keys.hmacShaKeyFor(secret.getBytes()))
            .compact();
    }


    /** 解析 Token 獲取用戶信息 */
    public User getUser(String token) {
        try {
            String info = (String) getClaimFromToken(token, claims -> claims.get("info"));
            return objectMapper.readValue(info, User.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        Claims claims = Jwts.parserBuilder()
            .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
            .build()
            .parseClaimsJws(token)
            .getBody();
        return claimsResolver.apply(claims);
    }
}

認證攔截器

package com.icoderoad.interceptor;


import com.icoderoad.utils.JwtUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.regex.*;


@Component
public class AuthInterceptor implements HandlerInterceptor {
    private static final Pattern AUTH_PATTERN = Pattern.compile("^Bearer (?<token>[a-zA-Z0-9-._~+/]+=*)$", Pattern.CASE_INSENSITIVE);


    private final JwtUtil jwtUtil;
    private final ObjectMapper objectMapper;


    public AuthInterceptor(JwtUtil jwtUtil, ObjectMapper objectMapper) {
        this.jwtUtil = jwtUtil;
        this.objectMapper = objectMapper;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (authorization == null || !authorization.startsWith("Bearer ")) {
            sendError(response, "缺失 Token");
            return false;
        }


        Matcher matcher = AUTH_PATTERN.matcher(authorization);
        if (!matcher.matches()) {
            sendError(response, "無效 Token");
            return false;
        }


        User user = jwtUtil.getUser(matcher.group("token"));
        if (user == null) {
            sendError(response, "登錄失效,請重新登錄");
            return false;
        }


        SecurityContext.setUser(user);
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        SecurityContext.clear();
    }


    private void sendError(HttpServletResponse response, String message) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(objectMapper.writeValueAsString(Map.of("code", -1, "message", message)));
    }
}

權限切面

package com.icoderoad.aspect;


import com.icoderoad.annotation.PreAuthorize;
import com.icoderoad.context.SecurityContext;
import com.icoderoad.exception.AuthException;
import com.icoderoad.model.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;


import java.util.Collections;
import java.util.Set;


@Aspect
@Component
public class PermissionAspect {
    @Around("@annotation(preAuthorize)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, PreAuthorize preAuthorize) throws Throwable {
        User user = SecurityContext.getUser();
        if (user == null) {
            throw new AuthException("請先登錄");
        }


        Set<String> requiredPerms = Set.of(preAuthorize.value());
        Set<String> userPerms = user.getPermissions();
        boolean hasPermission = validatePermissions(requiredPerms, userPerms, preAuthorize.logic());


        if (!hasPermission) {
            throw new AuthException("權限不足");
        }


        return joinPoint.proceed();
    }


    private boolean validatePermissions(Set<String> required, Set<String> has, PreAuthorize.Logical logic) 		{
        return logic == PreAuthorize.Logical.AND ? has.containsAll(required) : !Collections.disjoint(required, has);
    }
}

配置攔截器

package com.icoderoad.config;


import com.icoderoad.interceptor.AuthInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;


@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final AuthInterceptor authInterceptor;


    public WebConfig(AuthInterceptor authInterceptor) {
        this.authInterceptor = authInterceptor;
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/users/**");
    }
}

測試

package com.icoderoad.controller;


import com.icoderoad.model.User;
import com.icoderoad.util.JwtUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


import java.util.Map;
import java.util.Set;


@RestController
public class LoginController {
    private final JwtUtil jwtUtil;


    public LoginController(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }


    @GetMapping("/login")
    public ResponseEntity<Object> login(@RequestParam String username) {
        User user = new User(1L, username, Set.of("USER"));
        String token = jwtUtil.generateToken(user);
        return ResponseEntity.ok(Map.of("token", token));
    }
}

結論

通過本篇文章的學習,我們基于 Spring Boot 3.4 實現了一套高效、靈活的權限控制方案,核心組件包括:

  1. 自定義注解 @PreAuthorize
    用于定義方法級權限控制。
  2. 攔截器(Interceptor)用于解析 Token 并獲取用戶信息。
  3. AOP 切面在方法執行前進行權限校驗。
  4. 自定義參數解析器讓 Controller 層代碼更加簡潔優雅。

相比傳統的 Spring Security 方案,本方案的優勢在于:

  • 更加輕量級不依賴復雜的認證機制,僅需少量代碼即可實現。
  • 高度可擴展可以靈活適配不同的認證方式,如 JWT、OAuth2 等。
  • 代碼解耦業務邏輯與權限校驗分離,提升可維護性。

在實際項目中,該方案適用于對性能和靈活性要求較高的場景,開發者可以在此基礎上,結合自身業務需求,進一步優化和擴展,如 動態權限配置、RBAC(基于角色的訪問控制) 等。

如果你在 Spring Boot 3.4 版本的開發中,正在尋找一種 既安全又高效的權限控制方案,不妨嘗試本文介紹的方法,相信會給你的項目帶來新的啟發和幫助。


責任編輯:武曉燕 來源: 路條編程
相關推薦

2025-03-10 01:00:00

Spring參數解析器

2021-03-16 10:39:29

SpringBoot參數解析器

2022-07-11 10:37:41

MapPart集合

2024-10-14 17:18:27

2013-01-14 11:40:50

IBMdW

2022-05-11 10:45:21

SpringMVC框架Map

2022-01-06 06:23:49

Swagger參數解析器

2022-11-10 07:53:54

Spring參數校驗

2017-08-03 17:00:54

Springmvc任務執行器

2023-10-24 13:48:50

自定義注解舉值驗證

2024-02-22 08:06:45

JSON策略解析器

2020-11-25 11:20:44

Spring注解Java

2024-09-10 10:04:47

2018-06-21 14:46:03

Spring Boot異步調用

2024-12-27 15:37:23

2025-09-26 05:00:00

2021-10-12 10:50:31

鴻蒙HarmonyOS應用

2021-12-30 12:30:01

Java注解編譯器

2024-07-02 11:42:53

SpringRedis自定義

2024-10-09 10:46:41

springboot緩存redis
點贊
收藏

51CTO技術棧公眾號

亚洲第一在线综合网站| 成人免费观看视频大全| 日韩mv欧美mv国产网站| 欧美裸体一区二区三区| 日本一本二本在线观看| 成人羞羞在线观看网站| 亚洲免费av片| 日韩欧美小视频| 中文字幕制服丝袜一区二区三区| av一本久道久久波多野结衣| 精品三级在线| 日本高清视频一区| 四虎免费av| 国产尤物久久久| 国产精品视频一区国模私拍| 欧美黄色一区| 一区二区日本伦理| 亚洲精品福利视频网站| av影视在线看| 99国产精品久久久久久久成人热| 日韩成人在线播放| 都市激情综合| av在线不卡网| 99在线热播| 91九色露脸| 日韩av电影一区| 亚洲第一福利网站| 欧美激情午夜| 色悠悠亚洲一区二区| 久久天天东北熟女毛茸茸| 国语自产偷拍精品视频偷| 视频精品一区二区三区| 久久精品电影网| 国产在线精品一区二区三区》| 青青视频在线观| 风流少妇一区二区| 先锋影音资源999| 成人看的视频| 欧美在线一区二区三区四区| 99热精品国产| 久草视频在线看| xxav国产精品美女主播| 欧美日韩亚洲一区| 国产精品影院在线观看| 丝袜美腿综合| 色成年激情久久综合| 亚洲乱码一区二区三区| 粉嫩嫩av羞羞动漫久久久| 国产成人精品免费| 久久99久久99精品中文字幕 | 日本视频免费一区| 51久久精品夜色国产麻豆| 欧美精品尤物在线观看 | 蜜桃av色综合| 国产suv精品一区二区883| 亚洲视频在线一区| 国产免费毛卡片| 久久久久88色偷偷免费| www.日本少妇| 成人免费三级在线| 成人在线免费观看视频网站| 99久久久精品| 免费av在线网址| 欧美久久精品午夜青青大伊人| 99re6这里只有精品视频在线观看| 久久综合色8888| 日本wwwwww| 亚洲女同性videos| 亚洲欧洲日产国码二区| 在线观看网站免费入口在线观看国内| 日韩一区二区中文字幕| 欧美在线日韩| 国产第一页视频| 久久久电影一区二区三区| 免费看涩涩视频| 亚洲高清福利视频| 色欧美激情视频在线| 女人天堂av在线播放| 亚洲性生活视频在线观看| 一本色道久久加勒比88综合| 成人v精品蜜桃久久一区| 美日韩精品免费视频| 51亚洲精品| 黄页网站大全在线观看| 成人毛片视频在线观看| 色欲av无码一区二区人妻| 国产精品美女| 91精品国产综合久久久久久久久| 成人在线黄色电影| 亚洲第一av在线| 国产福利片在线观看| 国内精品一区二区三区| 美国十次了思思久久精品导航| 成人性a激情免费视频| 欧美色男人天堂| 久久在线91| 欧美精品七区| 欧美私人啪啪vps| 另类小说综合网| 日本午夜一本久久久综合| 老太脱裤让老头玩ⅹxxxx| 欧美精选一区二区| 九九久久精品| 日韩免费毛片视频| 在线精品视频视频中文字幕| 激情综合色丁香一区二区| 激情五月宗合网| 亚洲欧洲日本在线| ccyy激情综合| 欧美日韩大片一区二区三区| 午夜精品久久一牛影视| 欧美日韩一本到| 97影院秋霞午夜在线观看| 日韩一区二区精品视频| 91美女视频在线| 国产精品视频免费一区| 久久超碰亚洲| 欧美女人性生活视频| 天天射综合网站| 色视频www在线播放国产人成| 吴梦梦av在线| 97在线视频免费| 欧美片一区二区三区| 日韩中文字幕网| 亚洲第一狼人社区| 欧美性猛交xxxx乱大交极品| 久久精品水蜜桃av综合天堂| 欧美成人自拍| 超黄网站在线观看| 992tv免费直播在线观看| 亚洲国产精品久久久久爰色欲| 精品国内产的精品视频在线观看| 久久久久久日产精品| 欧美特黄一级大片| 秋霞成人影院| 99久久国产综合精品色伊| 日本999视频| 亚洲国产成人精品电影| 激情五月激情综合网| 亚洲在线黄色| 久久综合偷偷噜噜噜色| 怡红院亚洲色图| 欧美日韩视频在线一区二区观看视频 | 国内精品国语自产拍在线观看| 欧美高清dvd| 欧美艳星brazzers| 日本一区二区三区国色天香| 国产精品影视天天线| 制服丝袜日韩| 无遮挡在线观看| av片在线观看| 四虎在线精品| 日韩精品91| 日韩激情在线观看| 久久久久久亚洲综合| 色悠久久久久综合欧美99| 欧美精品99久久久**| 综合久久给合久久狠狠狠97色| 成人动漫在线一区| 久久这里只精品最新地址| 午夜激情一区| 亚洲成人精品综合在线| 久久国产精品久久久久久电车| 一区二区电影网| 欧美1819sex性处18免费| 午夜精品短视频| 国产九色精品| 成人字幕网zmw| 99免费在线观看视频| 91精品国产99| 亚洲国产色一区| 91福利国产成人精品照片| 97se亚洲国产综合自在线| 免费高清在线一区| 欧美日韩1080p| 鲁大师精品99久久久| 亚洲国产伊人| 国产日韩三级| 国产中文在线观看| 日韩国产91| 日本高清中文字幕在线| 成人在线免费看| 人人干人人干人人| 久久99久久精品国产| 91精选在线观看| 91色乱码一区二区三区| 国自产拍偷拍福利精品免费一 | 亚洲最大黄色| 黄网页免费在线观看| 欧洲av一区二区| 亚洲国产综合在线观看| www.成人在线视频| 日韩精品成人av| 国产精品一区hongkong| 136国产福利精品导航网址应用| 色婷婷综合久久久久久| 日韩成人精品一区| 国产原创一区| 日本美女在线中文版| 欧美性猛交p30|