亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java使用Cookie實現(xiàn)認證跳轉(zhuǎn)功能

 更新時間:2025年06月06日 09:38:37   作者:mr.Darker  
在?Web?開發(fā)中,用戶身份認證是一個基礎而關鍵的功能點,本文將通過一個簡單的前后端示例系統(tǒng),介紹如何基于?Cookie?實現(xiàn)?Token?保存與自動跳轉(zhuǎn)認證的功能,并結合?Cookie?與?Header?的區(qū)別、使用場景、安全性等維度做全面分析,需要的朋友可以參考下

一、Cookie 和 Header 的區(qū)別

項目CookieHeader
定義存儲在瀏覽器中的字段,用于保持用戶狀態(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 應該保存在配置文件中,而非隨機生成
  • 瀏覽器無法讀取 HttpOnly Cookie,確保安全性;如需前端讀 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)的資料請關注腳本之家其它相關文章!

相關文章

最新評論