---
# System prepended metadata

title: JWT

---

# JWT

## 前端實現

在需要進行認證的 API 請求前，使用以下程式碼：

```javascript
// 先引入 Auth.js <script th:src="@{/Token/auth.js}"></script>

// 檢查是否已登入
if (!Auth.isLoggedIn()) {
    // 如果未登入，重定向到登入頁面
    Auth.logout(); 
} else {
    // 已登入，準備 API 請求
    const ajaxParam = {
        headers: {
            'Authorization': `Bearer ${Auth.getToken()}`
        },
        params: {
            // 原本要傳送的 RequestBody
        }
    };

    // 發送 API 請求
    axios.get(url, ajaxParam)
        .then(response => {
            // 處理響應
        })
        .catch(error => {
            // 處理錯誤
            if (error.response && error.response.status === 401) {
                Auth.logout(); // 如果錯誤會移除token並自動定向到登入頁面
            }
        });
}
```

memberProfile.js部分範例
```javascript!
// 獲取會員資料
async function getMemberProfile() {
    if (!Auth.isLoggedIn()) {
        Auth.logout();
        return;
    }

    try {
        const response = await axios.get('/TickitEasy/api/member/profile', {
            headers: { 'Authorization': `Bearer ${Auth.getToken()}` }
        });
        console.log('API 回應:', response.data);
        updateProfileUI(response.data);
    } catch (error) {
        console.error('獲取會員資料時發生錯誤:', error);
        handleApiError(error);
    }
}
```


## 後端實現

Controller

```java
// 先 @Autowired JWTUtil jwtUtil;

@PostMapping("/your-endpoint")
public ResponseEntity<?> yourMethod(
        @RequestHeader("Authorization") String authHeader,
        @RequestBody Map<String, String> requestBody) {
    
    try {
        // 從 Authorization Header 中提取 Token
        String token = authHeader.replace("Bearer ", "");
        
        // 從 Token 中獲取電子郵件
        String email = jwtUtil.getEmailFromToken(token);
        
        // 根據電子郵件獲取會員資料
        Member member = memberService.findByEmail(email);
        
        if (member == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid user");
        }

        // 進行後續操作...
        
        return ResponseEntity.ok("操作成功");
    } catch (Exception e) {
        // 處理 Token 無效或過期的情況
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid or expired token");
    }
}
```
memberController部分範例
```java
 // 處理會員頭貼上傳（需驗證Token)
    @PostMapping("/profilePic")
    public ResponseEntity<Map<String, String>> uploadProfilePic(
            @RequestHeader("Authorization") String authHeader,
            @RequestParam("profilePic") MultipartFile profilePic) {
        Map<String, String> response = new HashMap<>();
        try {
            // 從 Authorization Header拿Token
            String token = authHeader.replace("Bearer ", "");
            // 從Token拿電子信箱
            String email = jwtUtil.getEmailFromToken(token);
            // 根據電子信箱拿到會員的資料
            Member currentMember = memberService.findByEmail(email);

            if (currentMember == null) {
                response.put("error", "會員不存在");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            // 處理頭貼上傳
            memberService.uploadProfilePic(currentMember.getMemberID(), profilePic);

            response.put("message", "頭貼上傳成功");
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            logger.error("頭貼上傳失敗：{}", e.getMessage());
            response.put("error", "頭貼上傳失敗");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        } catch (Exception e) {
            logger.error("錯誤：{}", e.getMessage());
            response.put("error", "發生錯誤，請稍後再試。");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }
```

### 補充

**前端：**
-    使用 Auth.getToken() 拿到JWT,並在每個API請求的header中包含它```
headers: {
            'Authorization': `Bearer ${Auth.getToken()}`
        },```
-    如果收到401錯誤(未授權),則調用 Auth.logout() 登出。


**後端：**

-    每個API都從 Authorization header中拿到JWT。
-    再用 jwtUtil 從token中拿到會員的email。
-    根據email找會員資料。
-    驗證會員不是null後才處理請求。