最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

項目CookieHeader
定義存儲在瀏覽器中的字段,用于保持用戶狀態(tài)HTTP 請求/響應的元數(shù)據(jù),描述請求數(shù)據(jù)信息
默認行為每次同域同路徑請求時自動被瀏覽器附加到請求中需要開發(fā)者手動在請求中配置
存儲可持久存儲在本地瀏覽器每次請求時重新傳送
與 JS 的關(guān)系如果設(shè)置 HttpOnly ,JS 無法讀取JS 可以自由操作 Header
通用場景登錄狀態(tài)保持,身份聲明JWT Token、代理等信息傳遞

總結(jié):

Cookie 更適合于 Web 應用自動附帶的狀態(tài)保持,Header 則適用于前后端分離、接口授權(quán)等場景。

此外,如果系統(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 和解析出的信息

三、項目結(jié)構(gòu)說明

本項目基于 Spring Boot 構(gòu)建,包含前后端組件,結(jié)構(gòu)如下:

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 是服務(wù)端自定義加密密鑰,推薦保存在配置文件中;
  • 可使用 Keys.secretKeyFor(SignatureAlgorithm.HS256) 動態(tài)生成,但不適合生產(chǎn),因為服務(wù)重啟后舊 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>

五、總結(jié)

  • Cookie 和 Header 各有優(yōu)勢,要根據(jù)場景選擇
  • 使用 Cookie 可以自動附加身份信息,適合 Web 項目
  • JWT 分布系統(tǒng)輕量、無狀態(tài)、可擴展
  • 固定 KEY 應該保存在配置文件中,而非隨機生成
  • 瀏覽器無法讀取 HttpOnly Cookie,確保安全性;如需前端讀 token,請將 HttpOnly = false

附錄:完整文件(可自行補全代碼)

Spring Boot 項目目錄結(jié)構(gòu)參考

src/main/java/org/example/
├── controller/
│   └── LoginController.java      # 登錄與驗證碼相關(guān)接口
├── 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)容,更多關(guān)于Java Cookie認證跳轉(zhuǎn)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java實現(xiàn)滑動驗證解鎖

    java實現(xiàn)滑動驗證解鎖

    這篇文章主要為大家詳細介紹了java實現(xiàn)滑動驗證解鎖,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 關(guān)于使用Lambda表達式簡化Comparator的使用問題

    關(guān)于使用Lambda表達式簡化Comparator的使用問題

    這篇文章主要介紹了關(guān)于使用Lambda表達式簡化Comparator的使用問題,文中圖文講解了Comparator對象的方法,需要的朋友可以參考下
    2023-04-04
  • Mybatis攔截器打印sql問題

    Mybatis攔截器打印sql問題

    這篇文章主要介紹了Mybatis攔截器打印sql問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 深入探討Java應用性能監(jiān)控與調(diào)優(yōu)的工具鏈構(gòu)建

    深入探討Java應用性能監(jiān)控與調(diào)優(yōu)的工具鏈構(gòu)建

    這篇文章主要來和大家將深入探討Java應用性能監(jiān)控與調(diào)優(yōu)的完整工具鏈,從傳統(tǒng)的單機分析工具JProfiler到現(xiàn)代化的分布式監(jiān)控系統(tǒng)Prometheus,希望能幫助開發(fā)者和運維人員構(gòu)建全方位的性能監(jiān)控體系
    2025-06-06
  • Java解析json報文實例解析

    Java解析json報文實例解析

    這篇文章主要介紹了Java解析json報文實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Spring占位符Placeholder的實現(xiàn)原理解析

    Spring占位符Placeholder的實現(xiàn)原理解析

    這篇文章主要介紹了Spring占位符Placeholder的實現(xiàn)原理,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Java?super、this、static關(guān)鍵字實踐案例

    Java?super、this、static關(guān)鍵字實踐案例

    本文詳細介紹了Java繼承的概念,包括繼承的本質(zhì)、創(chuàng)建子類對象的過程、方法重寫和方法重載的區(qū)別,以及Java的繼承層次,此外,還討論了super和this關(guān)鍵字的用法,以及static關(guān)鍵字的歸屬、內(nèi)存模型、靜態(tài)方法的調(diào)用限制和靜態(tài)代碼塊的執(zhí)行時機,感興趣的朋友一起看看吧
    2025-11-11
  • mybatis.type-aliases-package的作用及用法說明

    mybatis.type-aliases-package的作用及用法說明

    這篇文章主要介紹了mybatis.type-aliases-package的作用及用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 使用dom4j遞歸解析節(jié)點內(nèi)還含有多個節(jié)點的xml

    使用dom4j遞歸解析節(jié)點內(nèi)還含有多個節(jié)點的xml

    這篇文章主要介紹了使用dom4j遞歸解析節(jié)點內(nèi)還含有多個節(jié)點的xml,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Lombok中@Builder和@SuperBuilder注解的用法案例

    Lombok中@Builder和@SuperBuilder注解的用法案例

    @Builder?是?lombok?中的注解,可以使用builder()構(gòu)造的Person.PersonBuilder對象進行鏈式調(diào)用,給所有屬性依次賦值,這篇文章主要介紹了Lombok中@Builder和@SuperBuilder注解的用法,需要的朋友可以參考下
    2023-01-01

最新評論

宜章县| 武宁县| 宣恩县| 南澳县| 华安县| 塔河县| 乐安县| 连平县| 曲阜市| 宣威市| 汝南县| 桂平市| 大悟县| 米易县| 天气| 石棉县| 大埔区| 抚松县| 威海市| 右玉县| 民县| 文安县| 四川省| 六盘水市| 来凤县| 万盛区| 卓尼县| 江口县| 施甸县| 千阳县| 汤原县| 柏乡县| 绥化市| 德钦县| 贡觉县| 无棣县| 连云港市| 嵊泗县| 虎林市| 秀山| 汉川市|