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

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

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

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

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

總結(jié):

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

此外,如果系統(tǒng)是前后端分離或移動(dòng)端調(diào)用 API,推薦使用 Header + Bearer Token 的方式;而傳統(tǒng) Web 系統(tǒng)則更偏好基于 Cookie 的方案,方便瀏覽器自動(dòng)攜帶狀態(tài)。

二、功能需求簡(jiǎn)述

當(dāng)前系統(tǒng)需求并非完整用戶系統(tǒng)登錄,而是一個(gè)基于輸入 Token 的快速標(biāo)記機(jī)制,滿足以下目標(biāo):

  • 前端提供 Token(如 email)
  • 后端生成對(duì)應(yīng)的 JWT 并存入瀏覽器 Cookie
  • 后續(xù)訪問頁面時(shí):
    • 自動(dòng)讀取 Cookie 中的 JWT
    • 后端解析 JWT,確認(rèn)身份合法則自動(dòng)跳轉(zhuǎn)
    • 前端彈出提示當(dāng)前用戶 Token 和解析出的信息

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

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

MyTestJava
├── src/
│   └── main/
│       ├── java/
│       │   └── org.example/
│       │       ├── Main.java                     // SpringBoot 啟動(dòng)類
│       │       ├── controller/
│       │       │   └── TokenEntryController.java // 控制器:處理接口請(qǐng)求
│       │       └── util/
│       │           └── JwtUtils.java             // 工具類:生成/解析 JWT
│       └── resources/
│           ├── static/
│           │   └── index.html                    // 前端頁面
│           └── application.properties            // 配置文件
├── pom.xml                                       // Maven 配置

說明:

  • JwtUtils:JWT 的封裝生成器,負(fù)責(zé) create / parse
  • TokenEntryController:接口控制器,處理前端發(fā)送的 token 保存請(qǐng)求和驗(yàn)證請(qǐng)求
  • index.html:純前端展示頁面,包含輸入框與登錄判斷邏輯
  • application.properties:可配置端口、秘鑰等

四、代碼實(shí)現(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) 動(dòng)態(tài)生成,但不適合生產(chǎn),因?yà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="請(qǐng)輸入 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)勢(shì),要根據(jù)場(chǎng)景選擇
  • 使用 Cookie 可以自動(dòng)附加身份信息,適合 Web 項(xiàng)目
  • JWT 分布系統(tǒng)輕量、無狀態(tài)、可擴(kuò)展
  • 固定 KEY 應(yīng)該保存在配置文件中,而非隨機(jī)生成
  • 瀏覽器無法讀取 HttpOnly Cookie,確保安全性;如需前端讀 token,請(qǐng)將 HttpOnly = false

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

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

src/main/java/org/example/
├── controller/
│   └── LoginController.java      # 登錄與驗(yàn)證碼相關(guān)接口
├── model/
│   └── User.java                 # 用戶模型類
├── service/
│   └── UserService.java          # 登錄邏輯與驗(yàn)證碼緩存管理
├── util/
│   └── EmailSender.java          # 郵件發(fā)送工具類
└── Main.java                     # SpringBoot 啟動(dòng)類

src/main/resources/
├── static/index.html             # 前端測(cè)試頁面
└── application.properties        # 郵件 + Redis + DB 配置項(xiàng)

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 父項(xiàng)目 -->
    <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 實(shí)現(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 驗(yàn)證</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 無效");
                    }
                });
            }

            // 頁面加載后自動(dòng)訪問 entry 進(jìn)行判斷
            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 并驗(yàn)證跳轉(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);
    }
}

希望本文對(duì) Cookie 和 Header 在實(shí)際進(jìn)程中的使用有所啟發(fā),也為基于 Spring Boot 實(shí)現(xiàn)輕量登錄認(rèn)證提供思路。

以上就是Java使用Cookie實(shí)現(xiàn)認(rèn)證跳轉(zhuǎn)功能的詳細(xì)內(nèi)容,更多關(guān)于Java Cookie認(rèn)證跳轉(zhuǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談maven的jar包和war包區(qū)別 以及打包方法

    淺談maven的jar包和war包區(qū)別 以及打包方法

    下面小編就為大家分享一篇淺談maven的jar包和war包區(qū)別 以及打包方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助
    2017-11-11
  • Java如何用時(shí)間戳重命名上傳的文件

    Java如何用時(shí)間戳重命名上傳的文件

    這篇文章主要介紹了Java如何用時(shí)間戳重命名上傳的文件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 使用Java創(chuàng)建數(shù)據(jù)透視表并導(dǎo)出為PDF的方法

    使用Java創(chuàng)建數(shù)據(jù)透視表并導(dǎo)出為PDF的方法

    數(shù)據(jù)透視分析是一種強(qiáng)大的工具,可以幫助我們從大量數(shù)據(jù)中提取有用信息并進(jìn)行深入分析,本文將介紹如何使用Java來構(gòu)建PivotTable以及實(shí)現(xiàn)數(shù)據(jù)透視分析,并將其導(dǎo)出為PDF
    2023-10-10
  • Java實(shí)現(xiàn)分頁查詢功能

    Java實(shí)現(xiàn)分頁查詢功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)分頁查詢功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • spring boot如何指定啟動(dòng)端口

    spring boot如何指定啟動(dòng)端口

    這篇文章主要介紹了spring boot如何指定啟動(dòng)端口,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Spring實(shí)戰(zhàn)之ResourceLoaderAware加載資源用法示例

    Spring實(shí)戰(zhàn)之ResourceLoaderAware加載資源用法示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之ResourceLoaderAware加載資源用法,結(jié)合實(shí)例形式分析了spring使用ResourceLoaderAware加載資源相關(guān)配置與操作技巧,需要的朋友可以參考下
    2020-01-01
  • Spring mvc是如何實(shí)現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的?

    Spring mvc是如何實(shí)現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的?

    今天給大家?guī)淼氖顷P(guān)于Spring mvc的相關(guān)知識(shí),文章圍繞著Spring mvc是如何實(shí)現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法

    MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法

    今天小編就為大家分享一篇關(guān)于MapStruct處理Java中實(shí)體與模型間不匹配屬性轉(zhuǎn)換的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Spring?Boot教程之提高開發(fā)效率必備工具lombok

    Spring?Boot教程之提高開發(fā)效率必備工具lombok

    這篇文章主要介紹了Spring?Boot教程之提高開發(fā)效率必備工具lombok的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 詳解如何有效地處理Java中的多線程

    詳解如何有效地處理Java中的多線程

    在現(xiàn)代軟件開發(fā)中,多線程編程已成為提高程序性能和響應(yīng)速度的重要手段,Java提供了豐富的多線程支持,使得在Java中實(shí)現(xiàn)并發(fā)操作變得相對(duì)簡(jiǎn)單,本文將深入探討Java多線程編程的基本概念、常見問題和最佳實(shí)踐,需要的朋友可以參考下
    2024-06-06

最新評(píng)論