自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

爆火!Spring Boot 3.4 @HttpExchange 強勢來襲,一套搞定遠程調(diào)用 + 登錄認證 + Token續(xù)簽

開發(fā) 前端
如果你正在構(gòu)建一個現(xiàn)代化微服務(wù)系統(tǒng),并希望拋棄冗余依賴、提升遠程調(diào)用體驗與認證安全性,不妨從本文架構(gòu)出發(fā),打造一套真正面向未來的通信體系。?

本篇文章不僅展示如何使用@HttpExchange優(yōu)雅封裝遠程調(diào)用接口,還將結(jié)合 Spring Security、JWT、Redis 實現(xiàn)一體化登錄認證 + Token 續(xù)簽機制,并進一步集成:

  • ? Token 自動注入
  • ? 失敗自動重試
  • ? RefreshToken 自動續(xù)簽
  • ? Redis 緩存中間件管理 Token 生命周期 通過這些高級能力,你將看到一種真正“零侵入、強解耦、具備生產(chǎn)力”的服務(wù)通信與認證架構(gòu)。

核心依賴配置(Spring Boot 3.4.2)

<dependencies>
<!-- Webflux:用于 HttpExchange + WebClient -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- JWT -->
<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>

<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- 緩存工具(可選) -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
</dependencies>

application.yml 示例:

server:
port:8080

spring:
redis:
host: localhost
port:6379

jwt:
secret: icoderoad-secret
access-token-expire:600# 單位:秒
refresh-token-expire:1800# 單位:秒

JWT 工具類支持 AccessToken + RefreshToken:

@Component
public class JwtUtils {


    @Value("${jwt.secret}")
    private String secret;


    @Value("${jwt.access-token-expire}")
    private long accessExpire;


    @Value("${jwt.refresh-token-expire}")
    private long refreshExpire;


    // 生成 Token
    public String generateToken(String username, boolean isRefreshToken) {
        long expireTime = isRefreshToken ? refreshExpire : accessExpire;
        return Jwts.builder()
                .setSubject(username)
                .setExpiration(new Date(System.currentTimeMillis() + expireTime * 1000))
                .signWith(Keys.hmacShaKeyFor(secret.getBytes()))
                .compact();
    }


    public Claims parseToken(String token) throws JwtException {
        return Jwts.parserBuilder()
                .setSigningKey(secret.getBytes())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }


    public boolean isTokenExpired(String token) {
        return parseToken(token).getExpiration().before(new Date());
    }


    public long getAccessExpireMillis() {
        return accessExpire * 1000;
    }
}

登錄接口返回 Access + Refresh 雙 Token:

@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
    Authentication auth = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));


    String accessToken = jwtUtils.generateToken(request.getUsername(), false);
    String refreshToken = jwtUtils.generateToken(request.getUsername(), true);


    // 存入 Redis
    redisTemplate.opsForValue().set("access:" + accessToken, request.getUsername(),
            jwtUtils.getAccessExpireMillis(), TimeUnit.MILLISECONDS);
    redisTemplate.opsForValue().set("refresh:" + refreshToken, request.getUsername(),
            jwtUtils.getAccessExpireMillis() * 3, TimeUnit.MILLISECONDS);


    return ResponseEntity.ok(Map.of("accessToken", accessToken, "refreshToken", refreshToken));
}

Token 續(xù)簽邏輯(刷新接口):

@PostMapping("/refresh")
public ResponseEntity<?> refresh(@RequestBody Map<String, String> body) {
    String oldRefreshToken = body.get("refreshToken");
    try {
        Claims claims = jwtUtils.parseToken(oldRefreshToken);
        String username = claims.getSubject();


        // 校驗 Redis
        String redisUser = redisTemplate.opsForValue().get("refresh:" + oldRefreshToken);
        if (!username.equals(redisUser)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("無效的刷新Token");
        }


        // 新的 AccessToken
        String newAccessToken = jwtUtils.generateToken(username, false);
        redisTemplate.opsForValue().set("access:" + newAccessToken, username,
                jwtUtils.getAccessExpireMillis(), TimeUnit.MILLISECONDS);


        return ResponseEntity.ok(Map.of("accessToken", newAccessToken));
    } catch (JwtException e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Token非法或已過期");
    }
}

@HttpExchange 自動傳遞 Token 并支持異常重試:

@Configuration
public class RemoteClientConfig {


    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Bean
    public RemoteService remoteService(JwtUtils jwtUtils) {
        WebClient webClient = WebClient.builder()
                .baseUrl("http://localhost:8888")
                .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + fetchTokenFromRedis())
                .defaultStatusHandler(HttpStatusCode::isError, clientResponse -> {
                    return Mono.error(new RuntimeException("遠程服務(wù)異常"));
                })
                .filter(retryFilter())
                .build();


        WebClientAdapter adapter = WebClientAdapter.create(webClient);
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
        return factory.createClient(RemoteService.class);
    }


    private String fetchTokenFromRedis() {
        Set<String> keys = redisTemplate.keys("access:*");
        return keys != null && !keys.isEmpty() ? keys.iterator().next().substring(7) : "";
    }


    private ExchangeFilterFunction retryFilter() {
        return ExchangeFilterFunction.ofResponseProcessor(response -> {
            if (response.statusCode().is5xxServerError()) {
                return Mono.error(new IllegalStateException("服務(wù)不可用"));
            }
            return Mono.just(response);
        });
    }
}

總結(jié)

在本文中,我們基于 Spring Boot 3.4,構(gòu)建了一個功能完整的遠程服務(wù)通信與認證體系:

  • 使用@HttpExchange實現(xiàn)了極簡、聲明式的 HTTP 接口定義;
  • 借助 Spring WebClient 實現(xiàn)了底層 HTTP 請求執(zhí)行;
  • 通過 Spring Security + JWT + Redis 構(gòu)建了完整的登錄認證、Token 續(xù)簽與緩存管理機制;
  • 實現(xiàn)了 RefreshToken 自動續(xù)簽機制,提升了系統(tǒng)的安全性與用戶體驗;
  • 支持 Token 自動透傳、異常重試、參數(shù)對象映射等高級特性;

這一整套架構(gòu)的優(yōu)勢在于:

  1. 輕量純凈無需 Feign 等三方依賴,原生 Spring 實現(xiàn);
  2. 擴展性強支持異步響應(yīng)、參數(shù)自動注入、個性化異常處理;
  3. 認證鏈路可控可追溯Token 生命周期完全掌握在自己手中;
  4. 性能可期Token 與用戶狀態(tài)存于 Redis,讀寫高效,支撐高并發(fā)訪問場景。

如果你正在構(gòu)建一個現(xiàn)代化微服務(wù)系統(tǒng),并希望拋棄冗余依賴、提升遠程調(diào)用體驗與認證安全性,不妨從本文架構(gòu)出發(fā),打造一套真正面向未來的通信體系。

責任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2021-05-27 07:12:19

單點登錄系統(tǒng)

2010-12-24 11:27:13

華為HCNE認證

2025-02-17 00:00:45

接口支付寶沙箱

2020-01-02 16:30:02

Spring BootJava異步請求

2025-02-17 07:48:45

2025-04-08 08:01:31

2020-03-19 12:15:09

2024-02-20 08:56:50

JavaScript模塊打包器

2011-09-30 12:07:48

2019-10-11 15:58:25

戴爾

2015-08-03 11:50:18

灌水動畫

2023-11-06 10:41:46

ChatGPT馬斯克

2024-12-03 10:46:48

Spring優(yōu)化開發(fā)

2025-04-07 07:45:00

AI模型神經(jīng)網(wǎng)絡(luò)

2022-06-06 08:42:04

spring-boo開發(fā)接口防盜刷

2024-05-31 14:04:18

2009-06-23 18:01:45

Ajax框架源代碼

2018-08-31 08:42:48

LinuxUnix實用程序

2024-08-09 08:52:26

點贊
收藏

51CTO技術(shù)棧公眾號