欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Security+JWT如何實(shí)現(xiàn)前后端分離權(quán)限控制

 更新時間:2025年04月22日 15:26:25   作者:zru_9602  
本篇將手把手教你用?Spring?Security?+?JWT?搭建一套完整的登錄認(rèn)證與權(quán)限控制體系,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Spring Security+JWT實(shí)現(xiàn)前后端分離權(quán)限控制實(shí)戰(zhàn)

在前后端分離項(xiàng)目中,傳統(tǒng)的基于 Session 的認(rèn)證方式已不再適用。取而代之的是更加輕量、高效的 JWT(JSON Web Token)方式來實(shí)現(xiàn)無狀態(tài)認(rèn)證。

一、為什么要用 JWT?

前后端分離架構(gòu)的挑戰(zhàn):

  • 無法使用 Session 管理登錄狀態(tài)(前端和后端分離、跨域)
  • 需要一種「無狀態(tài)認(rèn)證機(jī)制

JWT 的優(yōu)勢:

  • 無需在服務(wù)端存儲會話信息(Token 自包含)
  • 結(jié)構(gòu)清晰,支持權(quán)限聲明(claims)
  • 可擴(kuò)展性強(qiáng),可用于 OAuth、SSO 等場景

二、JWT 基本結(jié)構(gòu)

一個 JWT Token 一般分為三段:

Header.Payload.Signature

例如:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNjg3NjQ5fQ.K4KgD1sE0JQzA1K6k-FaSd56fQ

每部分作用:

部分內(nèi)容
Header簽名算法,如 HS256
Payload載荷(如用戶名、角色、過期時間)
Signature簽名(防止篡改)

三、集成 JWT 的 Spring Security 權(quán)限控制思路

整體流程如下:

前端登錄 -> 后端驗(yàn)證用戶 -> 生成 JWT -> 返回給前端 -> 前端每次請求攜帶 Token -> 后端解析驗(yàn)證并授權(quán)

四、核心模塊代碼實(shí)戰(zhàn)

1. 引入依賴(Spring Boot 3.x 示例)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

2. JWT 工具類

@Component
public class JwtUtil {
    private final String SECRET = "MyJwtSecretKey123"; // 建議放到配置文件中
    private final long EXPIRATION = 1000 * 60 * 60; // 1小時

    public String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
            .signWith(SignatureAlgorithm.HS256, SECRET)
            .compact();
    }

    public String getUsernameFromToken(String token) {
        return Jwts.parser().setSigningKey(SECRET)
            .parseClaimsJws(token).getBody().getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

3. 自定義登錄接口生成 Token

@RestController
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        try {
            Authentication auth = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
            );
            String token = jwtUtil.generateToken(loginRequest.getUsername());
            return ResponseEntity.ok(Collections.singletonMap("token", token));
        } catch (AuthenticationException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用戶名或密碼錯誤");
        }
    }
}

4. JWT 認(rèn)證過濾器

@Component
public class JwtAuthFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            String username = jwtUtil.getUsernameFromToken(token);

            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);

                if (jwtUtil.validateToken(token)) {
                    UsernamePasswordAuthenticationToken authToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                    authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authToken);
                }
            }
        }

        chain.doFilter(request, response);
    }
}

5. 配置 SecurityFilterChain

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    @Autowired
    private JwtAuthFilter jwtAuthFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login").permitAll()
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
}

五、前端如何配合使用?

  1. 登錄后保存返回的 token
  2. 所有后續(xù)請求在 header 中添加:
Authorization: Bearer <你的 token>

六、權(quán)限控制示例

@RestController
public class UserController {

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/admin/data")
    public String adminData() {
        return "管理員數(shù)據(jù)";
    }

    @PreAuthorize("hasAnyRole('USER','ADMIN')")
    @GetMapping("/user/data")
    public String userData() {
        return "用戶數(shù)據(jù)";
    }
}

總結(jié)

JWT 與 Spring Security 的結(jié)合,可以幫助你構(gòu)建一個無狀態(tài)、安全、高效的前后端分離權(quán)限系統(tǒng)。它簡化了登錄狀態(tài)的管理流程,提高了系統(tǒng)的伸縮性與并發(fā)處理能力。

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論