Java使用Cookie實現(xiàn)認證跳轉(zhuǎn)功能
一、Cookie 和 Header 的區(qū)別
| 項目 | Cookie | Header |
|---|---|---|
| 定義 | 存儲在瀏覽器中的字段,用于保持用戶狀態(tài) | HTTP 請求/響應的元數(shù)據(jù),描述請求數(shù)據(jù)信息 |
| 默認行為 | 每次同域同路徑請求時自動被瀏覽器附加到請求中 | 需要開發(fā)者手動在請求中配置 |
| 存儲 | 可持久存儲在本地瀏覽器 | 每次請求時重新傳送 |
| 與 JS 的關系 | 如果設置 HttpOnly ,JS 無法讀取 | JS 可以自由操作 Header |
| 通用場景 | 登錄狀態(tài)保持,身份聲明 | JWT Token、代理等信息傳遞 |
總結:
Cookie 更適合于 Web 應用自動附帶的狀態(tài)保持,Header 則適用于前后端分離、接口授權等場景。
此外,如果系統(tǒng)是前后端分離或移動端調(diào)用 API,推薦使用 Header + Bearer Token 的方式;而傳統(tǒng) Web 系統(tǒng)則更偏好基于 Cookie 的方案,方便瀏覽器自動攜帶狀態(tài)。
二、功能需求簡述
當前系統(tǒng)需求并非完整用戶系統(tǒng)登錄,而是一個基于輸入 Token 的快速標記機制,滿足以下目標:
- 前端提供 Token(如 email)
- 后端生成對應的 JWT 并存入瀏覽器 Cookie
- 后續(xù)訪問頁面時:
- 自動讀取 Cookie 中的 JWT
- 后端解析 JWT,確認身份合法則自動跳轉(zhuǎn)
- 前端彈出提示當前用戶 Token 和解析出的信息

三、項目結構說明
本項目基于 Spring Boot 構建,包含前后端組件,結構如下:
MyTestJava ├── src/ │ └── main/ │ ├── java/ │ │ └── org.example/ │ │ ├── Main.java // SpringBoot 啟動類 │ │ ├── controller/ │ │ │ └── TokenEntryController.java // 控制器:處理接口請求 │ │ └── util/ │ │ └── JwtUtils.java // 工具類:生成/解析 JWT │ └── resources/ │ ├── static/ │ │ └── index.html // 前端頁面 │ └── application.properties // 配置文件 ├── pom.xml // Maven 配置
說明:
- JwtUtils:JWT 的封裝生成器,負責 create / parse
- TokenEntryController:接口控制器,處理前端發(fā)送的 token 保存請求和驗證請求
- index.html:純前端展示頁面,包含輸入框與登錄判斷邏輯
- application.properties:可配置端口、秘鑰等
四、代碼實現(xiàn)分析
JWT 工具類 JwtUtils
@Component
public class JwtUtils {
private static final String SECRET = "cT9gHD9Myp&Jz@3E*U2a%Ld!Fg#xZvPf";
private static final Key KEY = Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));
private static final long EXPIRATION = 30 * 24 * 60 * 60 * 1000L; // 30天
public String createToken(String email) {
return Jwts.builder()
.setSubject(email)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(KEY)
.compact();
}
public String parseToken(String token) {
try {
return Jwts.parserBuilder()
.setSigningKey(KEY)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
} catch (JwtException e) {
return null;
}
}
}
說明:
SECRET是服務端自定義加密密鑰,推薦保存在配置文件中;- 可使用
Keys.secretKeyFor(SignatureAlgorithm.HS256)動態(tài)生成,但不適合生產(chǎn),因為服務重啟后舊 token 將無法解析。
Controller: TokenEntryController
@RestController
@RequestMapping("/api")
public class TokenEntryController {
@Autowired
private JwtUtils jwtUtils;
@PostMapping("/token")
public ResponseEntity<Map<String, Object>> saveToken(@RequestBody Map<String, String> payload,
HttpServletResponse response) {
String email = payload.get("token");
String token = jwtUtils.createToken(email);
Cookie cookie = new Cookie("login_token", token);
cookie.setHttpOnly(true);
cookie.setPath("/");
cookie.setMaxAge(30 * 24 * 60 * 60);
response.addCookie(cookie);
return ResponseEntity.ok(Map.of(
"status", "success",
"redirectUrl", "https://www.baidu.com"
));
}
@GetMapping("/entry")
public ResponseEntity<Map<String, Object>> checkToken(@CookieValue(value = "login_token", required = false) String token) {
String email = jwtUtils.parseToken(token);
if (email != null) {
return ResponseEntity.ok(Map.of(
"status", "success",
"email", email,
"redirectUrl", "https://www.baidu.com"
));
} else {
return ResponseEntity.ok(Map.of("status", "fail"));
}
}
}
前端 HTML 邏輯
index.html 使用原生 JavaScript 與 Spring Boot 后端交互。
<input type="text" id="tokenInput" placeholder="請輸入 Email" />
<button onclick="sendToken()">發(fā)送</button>
<script>
function sendToken() {
const token = document.getElementById("tokenInput").value;
fetch("/api/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token })
})
.then(res => res.json())
.then(data => {
if (data.status === "success") {
window.location.href = data.redirectUrl;
}
});
}
window.onload = function () {
fetch("/api/entry")
.then(res => res.json())
.then(body => {
if (body.status === "success") {
const token = getCookie("login_token");
alert("已登錄\nToken: " + token + "\nEmail: " + body.email);
window.location.href = body.redirectUrl;
}
});
};
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? decodeURIComponent(match[2]) : null;
}
</script>
五、總結
- Cookie 和 Header 各有優(yōu)勢,要根據(jù)場景選擇
- 使用 Cookie 可以自動附加身份信息,適合 Web 項目
- JWT 分布系統(tǒng)輕量、無狀態(tài)、可擴展
- 固定 KEY 應該保存在配置文件中,而非隨機生成
- 瀏覽器無法讀取
HttpOnlyCookie,確保安全性;如需前端讀 token,請將 HttpOnly = false
附錄:完整文件(可自行補全代碼)
Spring Boot 項目目錄結構參考
src/main/java/org/example/ ├── controller/ │ └── LoginController.java # 登錄與驗證碼相關接口 ├── model/ │ └── User.java # 用戶模型類 ├── service/ │ └── UserService.java # 登錄邏輯與驗證碼緩存管理 ├── util/ │ └── EmailSender.java # 郵件發(fā)送工具類 └── Main.java # SpringBoot 啟動類 src/main/resources/ ├── static/index.html # 前端測試頁面 └── application.properties # 郵件 + Redis + DB 配置項
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>MyTestJava</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- Spring Boot 父項目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/>
</parent>
<dependencies>
<!-- Spring Boot Web 模塊(包含內(nèi)嵌 Tomcat) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot 開發(fā)工具模塊 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT 核心 API -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<!-- JWT 實現(xiàn)類 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- JWT 序列化/反序列化 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- Jakarta Servlet -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
index.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Token 驗證</title>
<style>
body {
background-color: #f0f2f5;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background-color: white;
padding: 30px 40px;
border-radius: 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
.input-group {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
input[type="text"] {
padding: 10px;
width: 220px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 6px;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #40a9ff;
}
</style>
</head>
<body>
<div class="container">
<div class="input-group">
<label for="token-input">
<input type="text" id="token-input" placeholder="輸入 Token" />
</label>
<button onclick="sendToken()">發(fā)送</button>
</div>
</div>
<script>
function sendToken() {
const token = document.getElementById("token-input").value;
fetch("/api/token", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ token })
})
.then(response => response.json())
.then(data => {
if (data.status === "success") {
window.location.href = data.redirectUrl;
} else {
alert("Token 無效");
}
});
}
// 頁面加載后自動訪問 entry 進行判斷
window.onload = function () {
fetch("/api/entry", { method: "GET" })
.then(response => {
if (!response.ok) return null;
return response.json();
})
.then(body => {
if (body && body.status === "success") {
alert("\n解析出的Email是:\n" + body.email);
window.location.href = body.redirectUrl;
}
})
.catch(err => {
console.error("檢查登錄狀態(tài)異常:", err);
});
};
</script>
</body>
</html>
Main.java
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* ==================================================
* This class ${NAME} is responsible for [功能描述].
*
* @author darker
* @version 1.0
* ==================================================
*/
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
JwtUtils.java
package org.example.util;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;
/**
* ==================================================
* This class JwtUtils is responsible for [功能描述].
*
* @author darker
* @version 1.0
* ==================================================
*/
@Component
public class JwtUtils {
private static final String SECRET = "cT9gHD9Myp&Jz@3E*U2a%Ld!Fg#xZvPf";
private static final Key KEY = Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));
private static final long EXPIRATION = 30 * 24 * 60 * 60 * 1000L; // 30天
public String createToken(String email) {
return Jwts.builder()
.setSubject(email)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(KEY)
.compact();
}
public String parseToken(String token) {
try {
return Jwts.parserBuilder()
.setSigningKey(KEY)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
} catch (JwtException e) {
return null; // 無效/過期
}
}
}
TokenEntryController.java
package org.example.controller;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import org.example.util.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* ==================================================
* This class TokenEntryController is responsible for [功能描述].
*
* @author draker
* @version 1.0
* ==================================================
*/
@RestController
@RequestMapping("/api")
public class TokenEntryController {
@Autowired
private JwtUtils jwtUtils;
/**
* 創(chuàng)建 Token 并寫入 Cookie
*/
@PostMapping("/token")
public ResponseEntity<Map<String, Object>> createToken(@RequestBody Map<String, String> payload,
HttpServletResponse response) {
String identity = payload.get("token"); // 可以是 email、userId 等
Map<String, Object> result = new HashMap<>();
if (identity == null || identity.isEmpty()) {
result.put("status", "fail");
return ResponseEntity.badRequest().body(result);
}
String token = jwtUtils.createToken(identity);
Cookie cookie = new Cookie("login_token", token);
cookie.setPath("/");
cookie.setHttpOnly(true);
cookie.setMaxAge(30 * 24 * 60 * 60); // 30 天
response.addCookie(cookie);
result.put("status", "success");
result.put("redirectUrl", "https://www.baidu.com");
return ResponseEntity.ok(result);
}
/**
* 檢查 Cookie 中的 Token 并驗證跳轉(zhuǎn)
*/
@GetMapping("/entry")
public ResponseEntity<Map<String, Object>> checkToken(@CookieValue(value = "login_token", required = false) String token) {
Map<String, Object> result = new HashMap<>();
if (token != null) {
String email = jwtUtils.parseToken(token);
if (email != null) {
result.put("status", "success");
result.put("email", email);
result.put("redirectUrl", "https://www.baidu.com");
return ResponseEntity.ok(result);
}
}
result.put("status", "fail");
return ResponseEntity.ok(result);
}
}
希望本文對 Cookie 和 Header 在實際進程中的使用有所啟發(fā),也為基于 Spring Boot 實現(xiàn)輕量登錄認證提供思路。
以上就是Java使用Cookie實現(xiàn)認證跳轉(zhuǎn)功能的詳細內(nèi)容,更多關于Java Cookie認證跳轉(zhuǎn)的資料請關注腳本之家其它相關文章!
相關文章
淺談maven的jar包和war包區(qū)別 以及打包方法
下面小編就為大家分享一篇淺談maven的jar包和war包區(qū)別 以及打包方法,具有很好的參考價值,希望對大家有所幫助2017-11-11
使用Java創(chuàng)建數(shù)據(jù)透視表并導出為PDF的方法
數(shù)據(jù)透視分析是一種強大的工具,可以幫助我們從大量數(shù)據(jù)中提取有用信息并進行深入分析,本文將介紹如何使用Java來構建PivotTable以及實現(xiàn)數(shù)據(jù)透視分析,并將其導出為PDF2023-10-10
Spring實戰(zhàn)之ResourceLoaderAware加載資源用法示例
這篇文章主要介紹了Spring實戰(zhàn)之ResourceLoaderAware加載資源用法,結合實例形式分析了spring使用ResourceLoaderAware加載資源相關配置與操作技巧,需要的朋友可以參考下2020-01-01
Spring mvc是如何實現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的?
今天給大家?guī)淼氖顷P于Spring mvc的相關知識,文章圍繞著Spring mvc是如何實現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下2021-06-06
MapStruct處理Java中實體與模型間不匹配屬性轉(zhuǎn)換的方法
今天小編就為大家分享一篇關于MapStruct處理Java中實體與模型間不匹配屬性轉(zhuǎn)換的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
Spring?Boot教程之提高開發(fā)效率必備工具lombok
這篇文章主要介紹了Spring?Boot教程之提高開發(fā)效率必備工具lombok的相關資料,需要的朋友可以參考下2022-08-08

