利用瀏覽器 Cookie 特性,可快速實作「同一使用者限點讚一次」的簡易防刷機制。雖無法完全防禦惡意竄改,但對一般爬蟲與重複點擊有顯著阻嚇效果,開發成本極低。
setMaxAge(秒數) 設定存活時間;負值 = 瀏覽器關閉即刪除;0 = 立即刪除。setPath("/") 讓全站可存取該 Cookie。Cookie cookie = new Cookie("like_123", "true");
response.addCookie(cookie); // 瀏覽器關閉即失效
Cookie cookie = new Cookie("like_123", "true");
cookie.setMaxAge(60 * 60 * 24 * 30); // 30 天
cookie.setPath("/"); // 全站可用
response.addCookie(cookie);
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
// 業務判斷邏輯
}
}
@RestController
@RequestMapping("/api/comment")
public class CommentController {
@Autowired
private CommentService commentService;
/**
* 點讚 API
* POST /api/comment/love
* 參數:commentId
*/
@PostMapping("/love")
public Map<String, Object> love(
@RequestParam Long commentId,
HttpServletRequest request,
HttpServletResponse response) {
Map<String, Object> result = new HashMap<>();
// 1. 依 commentId 組裝 Cookie 名稱
String cookieName = "like_" + commentId;
// 2. 檢查 Cookie 是否存在
Cookie cookie = findCookieByName(request, cookieName);
if (cookie != null) {
result.put("success", false);
result.put("msg", "您已點讚過,請稍後再試~");
return result;
}
// 3. 業務邏輯:資料庫點讚數 +1
commentService.incrementLikeCount(commentId);
// 4. 寫入 Cookie 防重複
addCookie(response, cookieName, "true", 30 * 24 * 60 * 60); // 30 天
result.put("success", true);
result.put("msg", "點讚成功");
return result;
}
// 工具方法:依名稱查找 Cookie
private Cookie findCookieByName(HttpServletRequest request, String name) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
if (name.equals(c.getName())) return c;
}
}
return null;
}
// 工具方法:新增 Cookie
private void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
Cookie cookie = new Cookie(name, value);
cookie.setMaxAge(maxAge);
cookie.setPath("/");
response.addCookie(cookie);
}
}
function likeComment(commentId) {
fetch('/api/comment/love', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'commentId=' + commentId
})
.then(r => r.json())
.then(data => {
if (data.success) {
alert('點讚成功!');
// 更新頁面顯示計數
} else {
alert(data.msg);
}
});
}
| 風險 | 說明 | 改進建議 |
|---|---|---|
| 用戶刪除 Cookie | 瀏覽器開發者工具可手動刪除 | 結合 IP 限制、登入狀態、裝置指紋 |
| 多裝置/多瀏覽器 | Cookie 不跨裝置共享 | 登入用戶改用資料庫記錄 user_id + comment_id |
| 惡意偽造請求 | 攻擊者可直接呼叫 API | 加入 CSRF Token、驗證碼、頻率限制 |