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

Spring Boot身份認證狀態(tài)的存儲與傳遞實現(xiàn)方案

 更新時間:2025年11月18日 09:14:17   作者:編程改變生活  
本文主要內(nèi)容介紹了在SpringBoot中實現(xiàn)用戶登錄信息獲取的三種主流方案:基于Session+Cookie、基于JWTToken和基于OAuth2.0/OIDC,并詳細介紹了每種方案的核心邏輯、代碼實現(xiàn)、優(yōu)缺點及關(guān)鍵注意點,感興趣的朋友跟隨小編一起看看吧

在 Spring Boot 中,瀏覽器獲取登錄信息的核心是 “身份認證狀態(tài)的存儲與傳遞”——登錄成功后,服務端會生成用戶身份憑證,瀏覽器通過特定機制存儲該憑證,后續(xù)請求時自動攜帶,服務端驗證憑證后即可識別用戶身份,返回對應的登錄信息。

以下是主流實現(xiàn)方案,從原理到具體操作逐步說明:

一、核心邏輯:登錄信息的“存儲-傳遞-驗證”流程

無論哪種方案,本質(zhì)都是3步:

  1. 登錄成功:用戶提交賬號密碼,服務端驗證通過后,生成包含用戶身份(如用戶ID、角色)的憑證(如Session ID、JWT Token);
  2. 憑證存儲:服務端存儲憑證與用戶信息的關(guān)聯(lián)(如Session內(nèi)存、Redis),瀏覽器存儲憑證(如Cookie、LocalStorage);
  3. 后續(xù)請求:瀏覽器攜帶憑證發(fā)起請求,服務端驗證憑證有效性,從關(guān)聯(lián)存儲中取出用戶信息,供業(yè)務使用(如返回用戶昵稱、權(quán)限)。

二、主流實現(xiàn)方案(按常用程度排序)

方案1:基于 Session + Cookie(傳統(tǒng)經(jīng)典方案)

這是 Spring Boot 整合 Spring Security/Shiro 時的默認方案,依賴 HTTP 協(xié)議的 Cookie 和服務端 Session 機制。

原理

  • Session:服務端創(chuàng)建的內(nèi)存/持久化存儲(如Redis),存儲用戶登錄信息(用戶ID、角色等),每個Session對應唯一的 JSESSIONID(憑證);
  • Cookie:瀏覽器自動存儲 JSESSIONID,后續(xù)請求時自動在 HTTP 頭的 Cookie 字段中攜帶該ID;
  • 流程
    1. 用戶登錄 → 服務端驗證通過 → 創(chuàng)建 Session(存儲用戶信息)→ 響應時通過 Set-Cookie 頭將 JSESSIONID 發(fā)送給瀏覽器;
    2. 瀏覽器保存 JSESSIONID 到 Cookie;
    3. 后續(xù)請求 → 瀏覽器自動攜帶 JSESSIONID(Cookie 字段)→ 服務端通過 JSESSIONID 找到對應的 Session → 取出用戶登錄信息。

代碼實現(xiàn)(Spring Security 示例)

  1. 引入依賴(Spring Boot 2.x+):
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 配置 Spring Security(默認啟用 Session + Cookie):
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 密碼加密器(Spring Security 要求密碼必須加密存儲)
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    // 模擬用戶(實際從數(shù)據(jù)庫查詢)
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password(passwordEncoder().encode("123456"))
            .roles("ADMIN"); // 存儲用戶角色(登錄信息的一部分)
    }
    // 授權(quán)規(guī)則(登錄接口允許匿名訪問)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/login").permitAll() // 登錄接口匿名訪問
                .anyRequest().authenticated() // 其他接口需登錄
            .and()
                .formLogin() // 啟用默認登錄頁面(或自定義 loginPage)
                .defaultSuccessUrl("/user/info") // 登錄成功后跳轉(zhuǎn)的接口(獲取登錄信息)
            .and()
                .logout()
                .permitAll();
    }
}
  1. 編寫接口,獲取當前登錄用戶信息:
@RestController
@RequestMapping("/user")
public class UserController {
    // 從 SecurityContext 中獲取登錄用戶信息(Spring Security 自動注入)
    @GetMapping("/info")
    public Principal getLoginUser(Principal principal) {
        // Principal 包含用戶名,如需更多信息(如用戶ID、昵稱),需自定義 User 類
        return principal;
    }
}
  1. 瀏覽器端表現(xiàn):
  • 登錄成功后,瀏覽器會在 Cookie 中存儲 JSESSIONID;
  • 后續(xù)訪問 /user/info 時,瀏覽器自動攜帶 JSESSIONID,服務端驗證后返回當前登錄用戶(如 {"name":"admin"})。

特點

  • 優(yōu)點:簡單易用,無需前端額外處理(Cookie 自動攜帶),安全性較高(可配置 Cookie 為 HttpOnly 防止 XSS 攻擊);
  • 缺點:依賴 Cookie,跨域場景需額外配置(如 CORS + Credentials),分布式部署需共享 Session(如 Redis 存儲 Session)。

方案2:基于 JWT Token(無狀態(tài)方案,適合前后端分離/跨域)

JWT(JSON Web Token)是一種無狀態(tài)憑證,登錄成功后服務端生成 Token 并返回給瀏覽器,瀏覽器存儲 Token(如 LocalStorage),后續(xù)請求通過 HTTP 頭(如 Authorization: Bearer Token)攜帶 Token,服務端解析 Token 即可獲取用戶信息。

原理

  • JWT 結(jié)構(gòu):由 Header(算法)、Payload(用戶信息,如用戶ID、用戶名)、Signature(簽名,防止篡改)三部分組成,用 . 拼接;
  • 流程
    1. 用戶登錄 → 服務端驗證通過 → 生成 JWT Token(Payload 中嵌入用戶信息)→ 返回 Token 給瀏覽器;
    2. 瀏覽器將 Token 存儲到 LocalStorage/SessionStorage;
    3. 后續(xù)請求 → 前端在請求頭中添加 Authorization: Bearer ${Token} → 服務端驗證 Token 簽名(確保未篡改)→ 解析 Payload 中的用戶信息。

代碼實現(xiàn)(Spring Security + JWT)

  1. 引入依賴(除 Spring Security 外,需添加 JWT 依賴):
<!-- JWT 依賴 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
  1. 編寫 JWT 工具類(生成 Token、驗證 Token、解析用戶信息):
@Component
public class JwtUtil {
    // 密鑰(生產(chǎn)環(huán)境需配置在配置文件,且定期更換)
    private static final String SECRET = "your-secret-key-32bytes-long-123456";
    // Token 過期時間(如 2 小時)
    private static final long EXPIRATION = 7200000;
    // 生成 Token(登錄成功后調(diào)用)
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", userDetails.getUsername());
        claims.put("roles", userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList()));
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
                .signWith(SignatureAlgorithm.HS256, SECRET)
                .compact();
    }
    // 驗證 Token 有效性
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    // 從 Token 中解析用戶信息(如用戶名)
    public String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
        return (String) claims.get("username");
    }
}
  1. 配置 Spring Security(禁用 Session,使用 JWT 認證):
@Configuration
@EnableWebSecurity
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private UserDetailsService userDetailsService; // 自定義用戶查詢服務(從數(shù)據(jù)庫取用戶)
    // 認證過濾器:解析請求頭中的 Token,驗證后注入用戶信息到 SecurityContext
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter(jwtUtil, userDetailsService);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable() // 前后端分離場景禁用 CSRF(Token 本身已防篡改)
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 禁用 Session
            .and()
            .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); // 添加 JWT 過濾器
    }
}
  1. 登錄接口(生成 Token 并返回):
@RestController
public class LoginController {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtUtil jwtUtil;
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        // 驗證賬號密碼
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        // 生成 JWT Token
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        String token = jwtUtil.generateToken(userDetails);
        // 返回 Token 給瀏覽器
        return ResponseEntity.ok(new JwtResponse(token));
    }
}
// 接收登錄請求的實體類
@Data
class LoginRequest {
    private String username;
    private String password;
}
// 返回 Token 的實體類
@Data
class JwtResponse {
    private String token;
    public JwtResponse(String token) {
        this.token = token;
    }
}
  1. 瀏覽器端處理:
  • 登錄成功后,前端將 Token 存儲到 localStorage
    // 登錄請求
    fetch('/login', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({username: 'admin', password: '123456'})
    })
    .then(res => res.json())
    .then(data => {
        localStorage.setItem('token', data.token); // 存儲 Token
    });
    // 后續(xù)請求(攜帶 Token)
    fetch('/user/info', {
        headers: {
            'Authorization': `Bearer ${localStorage.getItem('token')}` // 攜帶 Token
        }
    })
    .then(res => res.json())
    .then(userInfo => console.log('登錄用戶信息:', userInfo));

特點

  • 優(yōu)點:無狀態(tài)(服務端無需存儲 Session),支持跨域、分布式部署(Token 自帶用戶信息),適合前后端分離項目;
  • 缺點:Token 一旦生成無法主動撤銷(需通過過期時間控制或維護黑名單),Payload 不加密(敏感信息需加密存儲),前端需手動處理 Token 存儲與攜帶。

方案3:基于 OAuth2.0/OIDC(第三方登錄,如微信、QQ、GitHub)

如果需要支持第三方登錄(用戶無需注冊,通過微信/QQ 等賬號登錄),則使用 OAuth2.0 + OIDC 協(xié)議,瀏覽器通過第三方授權(quán)獲取身份憑證,服務端驗證后獲取用戶信息。

核心流程

  1. 瀏覽器跳轉(zhuǎn)第三方授權(quán)頁面(如微信登錄頁);
  2. 用戶授權(quán)后,第三方平臺返回 code 給瀏覽器;
  3. 瀏覽器將 code 發(fā)送給后端,后端通過 code 向第三方平臺請求 access_token;
  4. 后端用 access_token 調(diào)用第三方平臺的用戶信息接口(如微信的 /sns/userinfo),獲取用戶昵稱、頭像等信息;
  5. 后端將第三方用戶信息與本地用戶關(guān)聯(lián)(或自動注冊),生成本地登錄憑證(如 Session/JWT),返回給瀏覽器。

代碼實現(xiàn)(Spring Security OAuth2.0 示例,以 GitHub 登錄為例)

  1. 引入依賴:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
  1. 配置 GitHub OAuth2.0 信息(application.yml):
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: 你的GitHub客戶端ID(從GitHub開發(fā)者平臺申請)
            client-secret: 你的GitHub客戶端密鑰
            scope: user:email,read:user # 申請的權(quán)限(獲取用戶郵箱、基本信息)
        provider:
          github:
            user-info-uri: https://api.github.com/user
            email-attribute-name: email
  1. 配置 Spring Security(啟用 OAuth2.0 登錄):
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .oauth2Login() // 啟用 OAuth2.0 登錄
                .defaultSuccessUrl("/user/info", true) // 登錄成功后跳轉(zhuǎn)獲取用戶信息
                .userInfoEndpoint()
                .userService(customOAuth2UserService); // 自定義用戶信息處理(關(guān)聯(lián)本地用戶)
    }
}
  1. 獲取登錄用戶信息接口:
@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("/info")
    public OAuth2User getLoginUser(Authentication authentication) {
        // OAuth2User 包含第三方用戶信息(如GitHub昵稱、頭像、ID)
        return (OAuth2User) authentication.getPrincipal();
    }
}
  1. 瀏覽器端表現(xiàn):
  • 訪問 /user/info 時,自動跳轉(zhuǎn) GitHub 登錄頁;
  • 用戶登錄授權(quán)后,跳轉(zhuǎn)回 /user/info,返回 GitHub 用戶信息(如昵稱、頭像URL)。

三、關(guān)鍵注意點

  • 安全性
    • Session + Cookie:配置 Cookie 為 HttpOnly(防止 XSS 攻擊)、Secure(僅 HTTPS 傳輸)、SameSite(防止 CSRF 攻擊);
    • JWT:密鑰需足夠復雜且定期更換,敏感信息(如密碼)不能存入 Payload(Payload 可解碼),Token 過期時間不宜過長;
    • 所有方案都建議使用 HTTPS 傳輸,防止憑證被竊取。
  • 用戶信息擴展
    • 默認的 Principal/UserDetails 僅包含用戶名和角色,如需用戶ID、昵稱、郵箱等信息,需自定義 User 類實現(xiàn) UserDetails,并在登錄時注入。
  • 跨域處理
    • Session + Cookie:跨域時需配置 CORS 允許 credentials(憑證),前端請求需攜帶 withCredentials: true;
    • JWT:無跨域限制(Token 通過請求頭攜帶),只需配置 CORS 允許 Authorization 頭。
  • 分布式部署
    • Session + Cookie:需將 Session 存儲到共享介質(zhì)(如 Redis),通過 spring-session-data-redis 依賴實現(xiàn);
    • JWT:天然支持分布式(無狀態(tài)),無需額外配置。

總結(jié)

  • 傳統(tǒng)項目/非前后端分離:優(yōu)先使用 Session + Cookie(簡單、安全、無需前端額外處理);
  • 前后端分離/跨域/分布式項目:優(yōu)先使用 JWT Token(無狀態(tài)、易擴展);
  • 第三方登錄場景:使用 OAuth2.0/OIDC(對接微信、GitHub 等平臺)。

無論哪種方案,瀏覽器獲取登錄信息的核心都是通過憑證關(guān)聯(lián)服務端的用戶身份,差異僅在于憑證的存儲方式(Cookie/LocalStorage)和傳遞方式(自動攜帶/手動添加請求頭)。

到此這篇關(guān)于Spring Boot身份認證狀態(tài)的存儲與傳遞實現(xiàn)方案的文章就介紹到這了,更多相關(guān)Spring Boot身份認證狀態(tài)存儲與傳遞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion問題解決方法

    java.lang.AbstractMethodError: org.apache.xerces.dom.Documen

    這篇文章主要介紹了java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion問題解決方法,導致本文問題的原因是缺少一個xerces.jar jar包,需要的朋友可以參考下
    2015-03-03
  • Java獲取Word文檔中修訂記錄的實現(xiàn)方法

    Java獲取Word文檔中修訂記錄的實現(xiàn)方法

    在文檔協(xié)作與審閱場景中,Word 的修訂功能是一個常用工具,啟用該功能后,文檔中的所有編輯操作都會被記錄為修訂,本文將介紹如何使用 Java 語言,借助 Spire.Doc for Java 庫,從 Word 文檔中提取所有的修訂記錄,需要的朋友可以參考下
    2026-05-05
  • SpringMVC 使用JSR-303進行校驗 @Valid示例

    SpringMVC 使用JSR-303進行校驗 @Valid示例

    本篇文章主要介紹了SpringMVC 使用JSR-303進行校驗 @Valid示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • springboot的緩存技術(shù)的實現(xiàn)

    springboot的緩存技術(shù)的實現(xiàn)

    這篇文章主要介紹了springboot的緩存技術(shù)的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • SpringBoot中dubbo+zookeeper實現(xiàn)分布式開發(fā)的應用詳解

    SpringBoot中dubbo+zookeeper實現(xiàn)分布式開發(fā)的應用詳解

    這篇文章主要介紹了SpringBoot中dubbo+zookeeper實現(xiàn)分布式開發(fā)的應用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • Java線程狀態(tài)及jstack命令詳解

    Java線程狀態(tài)及jstack命令詳解

    jstack是Java虛擬機(JVM)提供的一個非常有用的命令行工具,它允許開發(fā)人員和系統(tǒng)管理員在運行時獲取Java應用程序的線程堆棧跟蹤,在某些情況下,可能需要以管理員或root用戶的身份運行jstack命令,這篇文章主要介紹了Java線程狀態(tài)及jstack命令詳解,需要的朋友可以參考下
    2024-03-03
  • Mybatis批量插入Oracle數(shù)據(jù)的方法實例

    Mybatis批量插入Oracle數(shù)據(jù)的方法實例

    在開發(fā)中或多或少都會遇到數(shù)據(jù)批量插入的功能,最近我在做項目的過程中就遇到了這樣一個問題,下面這篇文章主要給大家介紹了關(guān)于Mybatis批量插入Oracle數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • SpringBoot搭建go-cqhttp機器人的方法實現(xiàn)

    SpringBoot搭建go-cqhttp機器人的方法實現(xiàn)

    本文主要介紹了SpringBoot搭建go-cqhttp機器人的方法實現(xiàn)
    2021-12-12
  • SpringBoot實現(xiàn)多數(shù)據(jù)源配置的示例詳解

    SpringBoot實現(xiàn)多數(shù)據(jù)源配置的示例詳解

    這篇文章主要為大家詳細介紹了SpringBoot實現(xiàn)多數(shù)據(jù)源配置的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-12-12
  • SpringBoot連接Microsoft SQL Server實現(xiàn)登錄驗證

    SpringBoot連接Microsoft SQL Server實現(xiàn)登錄驗證

    本文主要介紹了SpringBoot連接Microsoft SQL Server實現(xiàn)登錄驗證,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-05-05

最新評論

鹿泉市| 江都市| 常山县| 定西市| 静安区| 宜兴市| 时尚| 玛曲县| 思南县| 九龙县| 淄博市| 诸城市| 酒泉市| 尤溪县| 凯里市| 密山市| 万山特区| 广宗县| 万山特区| 天峻县| 杨浦区| 诸暨市| 兴国县| 长子县| 犍为县| 裕民县| 固镇县| 通城县| 剑河县| 湖州市| 绍兴县| 涡阳县| 青河县| 鹰潭市| 兰州市| 曲水县| 津市市| 吴江市| 社旗县| 汝城县| 当阳市|