# 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後才處理請求。