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

Redis實(shí)現(xiàn)會(huì)話管理和token認(rèn)證的示例代碼

 更新時(shí)間:2025年04月22日 09:54:50   作者:昱晏  
會(huì)話管理和身份認(rèn)證是實(shí)現(xiàn)用戶登錄、權(quán)限管理等功能的基礎(chǔ),本文主就來(lái)介紹一下Redis實(shí)現(xiàn)會(huì)話管理和token認(rèn)證的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下

在現(xiàn)代Web應(yīng)用中,會(huì)話管理身份認(rèn)證是實(shí)現(xiàn)用戶登錄、權(quán)限管理等功能的基礎(chǔ)。傳統(tǒng)的會(huì)話管理通過(guò)服務(wù)器端保存會(huì)話信息來(lái)實(shí)現(xiàn),但隨著應(yīng)用的擴(kuò)展,尤其在分布式系統(tǒng)中,這種方式的局限性逐漸顯現(xiàn)。Redis作為分布式緩存系統(tǒng),具備高性能和高可用性,能夠很好地解決分布式環(huán)境下的會(huì)話管理和Token認(rèn)證問(wèn)題。

本教程將介紹如何基于Redis和Spring Boot 實(shí)現(xiàn)會(huì)話管理與Token認(rèn)證,確保應(yīng)用在高并發(fā)、分布式架構(gòu)中具備良好的性能和擴(kuò)展性。

一、使用場(chǎng)景

  • 分布式系統(tǒng):當(dāng)系統(tǒng)部署在多個(gè)服務(wù)實(shí)例上時(shí),服務(wù)器本地的Session無(wú)法跨實(shí)例共享,而Redis能作為集中式存儲(chǔ),幫助管理所有實(shí)例的會(huì)話信息。
  • 無(wú)狀態(tài)認(rèn)證:基于Token認(rèn)證機(jī)制的實(shí)現(xiàn),特別是JWT(JSON Web Token),適用于用戶登錄后通過(guò)Token進(jìn)行認(rèn)證,避免在每次請(qǐng)求時(shí)重新查詢數(shù)據(jù)庫(kù)或讀取Session。
  • 高并發(fā)場(chǎng)景:在高并發(fā)的情況下,Redis的高吞吐量和低延遲能夠保證會(huì)話管理和認(rèn)證機(jī)制的高效性。

二、原理解析

1. 會(huì)話管理

傳統(tǒng)的會(huì)話管理通過(guò)在服務(wù)器端保存用戶的會(huì)話狀態(tài)(Session),并通過(guò)客戶端(通常是瀏覽器)保存的Session ID與服務(wù)器進(jìn)行匹配,來(lái)確定用戶身份。在分布式環(huán)境下,本地Session機(jī)制無(wú)法保證跨實(shí)例共享,而Redis作為集中式存儲(chǔ),能夠提供跨服務(wù)實(shí)例的會(huì)話共享機(jī)制。

2. Token認(rèn)證

Token認(rèn)證,尤其是基于JWT的認(rèn)證方式,是一種無(wú)狀態(tài)認(rèn)證方案。與傳統(tǒng)的Session機(jī)制不同,JWT將用戶信息封裝在Token中,發(fā)送給客戶端,客戶端在后續(xù)請(qǐng)求中攜帶該Token進(jìn)行認(rèn)證,服務(wù)器通過(guò)驗(yàn)證Token來(lái)確定用戶身份。Redis可以用作存儲(chǔ)Token的有效期或與其他用戶數(shù)據(jù)的映射。

3. Redis在會(huì)話管理和Token認(rèn)證中的角色

  • 會(huì)話管理:將用戶的會(huì)話信息存儲(chǔ)在Redis中,保證分布式系統(tǒng)中不同實(shí)例對(duì)會(huì)話的共享訪問(wèn)。
  • Token認(rèn)證:存儲(chǔ)Token的有效性和用戶信息,或用于存儲(chǔ)黑名單Token(已失效或已注銷(xiāo)的Token)。

三、解決方案實(shí)現(xiàn)

1. 環(huán)境配置

首先,在pom.xml中添加Redis和Spring Security相關(guān)依賴(lài):

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- JWT Token -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.2</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.2</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.2</version>
    </dependency>
</dependencies>

application.yml中配置Redis:

spring:
  redis:
    host: localhost
    port: 6379
    timeout: 6000ms

2. Redis會(huì)話管理實(shí)現(xiàn)

在Spring Boot中,我們可以通過(guò)Redis來(lái)管理會(huì)話信息,下面的示例代碼展示如何使用Redis來(lái)存儲(chǔ)用戶會(huì)話信息。

配置Redis序列化器

為了使得對(duì)象能夠存儲(chǔ)在Redis中,我們需要配置Redis的序列化方式。

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 設(shè)置Key和Value的序列化器
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        
        return template;
    }
}

使用Redis存儲(chǔ)Session信息

我們可以在用戶登錄后將會(huì)話信息存入Redis中。

@Service
public class SessionService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void saveSession(String sessionId, Object sessionData) {
        redisTemplate.opsForValue().set(sessionId, sessionData, 30, TimeUnit.MINUTES); // 會(huì)話有效期30分鐘
    }

    public Object getSession(String sessionId) {
        return redisTemplate.opsForValue().get(sessionId);
    }

    public void deleteSession(String sessionId) {
        redisTemplate.delete(sessionId);
    }
}

3. Token認(rèn)證實(shí)現(xiàn)

JWT生成與解析

JWT是無(wú)狀態(tài)的認(rèn)證方式,將用戶信息封裝在Token中,通過(guò)數(shù)字簽名保證Token的安全性。我們使用jjwt庫(kù)來(lái)生成和解析JWT。

JWT工具類(lèi)

@Service
public class JwtTokenProvider {

    private static final String SECRET_KEY = "yourSecretKey";

    // 生成Token
    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // Token有效期1小時(shí)
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }

    // 解析Token
    public String getUsernameFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }

    // 驗(yàn)證Token是否過(guò)期
    public boolean isTokenExpired(String token) {
        Date expiration = Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .getExpiration();
        return expiration.before(new Date());
    }
}

JWT攔截器實(shí)現(xiàn)

為了在每次請(qǐng)求時(shí)驗(yàn)證Token的有效性,我們可以通過(guò)攔截器在請(qǐng)求到達(dá)控制器之前進(jìn)行校驗(yàn)。

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = getTokenFromRequest(request);
        
        if (token != null && !jwtTokenProvider.isTokenExpired(token)) {
            String username = jwtTokenProvider.getUsernameFromToken(token);
            // 在SecurityContext中設(shè)置認(rèn)證信息
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        
        filterChain.doFilter(request, response);
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

將攔截器添加到Spring Security配置中

我們需要將JwtAuthenticationFilter加入到Spring Security的過(guò)濾器鏈中。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/login", "/register").permitAll()  // 登錄、注冊(cè)請(qǐng)求不需要認(rèn)證
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

4. Token與Redis的結(jié)合

為了進(jìn)一步增強(qiáng)安全性,我們可以將生成的Token存儲(chǔ)在Redis中,并設(shè)置一個(gè)過(guò)期時(shí)間。當(dāng)Token失效或用戶登出時(shí),將其從Redis中移除。

@Service
public class TokenService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    public String createToken(String username) {
        String token = jwtTokenProvider.generateToken(username);
        redisTemplate.opsForValue().set(username, token, 1, TimeUnit.HOURS);  // Token存儲(chǔ)在Redis中,1小時(shí)過(guò)期
        return token;
    }

    public boolean validateToken(String token) {
        String username = jwt
        String username = jwtTokenProvider.getUsernameFromToken(token);
        String redisToken = (String) redisTemplate.opsForValue().get(username);
        return token.equals(redisToken) &amp;&amp; !jwtTokenProvider.isTokenExpired(token);
    }

    public void invalidateToken(String username) {
        redisTemplate.delete(username);  // 從Redis中移除Token
    }
}

5. 登錄接口實(shí)現(xiàn)

用戶登錄成功后,生成Token并存儲(chǔ)到Redis中,同時(shí)將Token返回給客戶端??蛻舳嗽诤罄m(xù)的請(qǐng)求中攜帶此Token。

@RestController
@RequestMapping("/auth")
public class AuthController {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private AuthenticationManager authenticationManager;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
        try {
            // 認(rèn)證用戶
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                    loginRequest.getUsername(), loginRequest.getPassword()));
            
            SecurityContextHolder.getContext().setAuthentication(authentication);
            
            // 生成Token并存儲(chǔ)到Redis
            String token = tokenService.createToken(loginRequest.getUsername());
            
            return ResponseEntity.ok(new JwtResponse(token));
        } catch (AuthenticationException e) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Authentication failed");
        }
    }

    @PostMapping("/logout")
    public ResponseEntity<?> logout(HttpServletRequest request) {
        String token = getTokenFromRequest(request);
        if (token != null) {
            String username = jwtTokenProvider.getUsernameFromToken(token);
            tokenService.invalidateToken(username);  // 從Redis中移除Token
        }
        return ResponseEntity.ok("Logout successful");
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

6. 請(qǐng)求流程示例

  • 用戶登錄:用戶提供用戶名和密碼,通過(guò)/auth/login接口進(jìn)行登錄。成功后,服務(wù)器生成JWT Token并存入Redis,并返回給客戶端。
  • Token攜帶請(qǐng)求:客戶端在后續(xù)的請(qǐng)求中,將Token放在Authorization頭部中,發(fā)送到服務(wù)器。服務(wù)器在收到請(qǐng)求后,通過(guò)JWT解析Token,驗(yàn)證有效性。
  • 登出操作:用戶在登出時(shí),前端請(qǐng)求/auth/logout接口,服務(wù)器將用戶的Token從Redis中移除,Token失效。

四、Redis會(huì)話管理與Token認(rèn)證效果

  • 高效性能:Redis的高并發(fā)讀寫(xiě)能力保證了在高并發(fā)場(chǎng)景下的會(huì)話存儲(chǔ)與Token驗(yàn)證的高效性。
  • 分布式支持:使用Redis作為集中存儲(chǔ),可以確保在多實(shí)例或分布式部署環(huán)境中共享會(huì)話數(shù)據(jù),避免本地Session的局限性。
  • 安全性增強(qiáng):通過(guò)Redis存儲(chǔ)Token以及Token的有效期控制,可以快速實(shí)現(xiàn)Token的失效處理,增強(qiáng)了安全性。

五、總結(jié)

Redis不僅能解決分布式環(huán)境下會(huì)話共享的問(wèn)題,也能通過(guò)高效存儲(chǔ)和快速讀取實(shí)現(xiàn)了Token認(rèn)證的高性能處理。在Spring Boot 中,使用Redis與JWT結(jié)合的方案為分布式架構(gòu)提供了強(qiáng)大的認(rèn)證與授權(quán)支持。

到此這篇關(guān)于Redis實(shí)現(xiàn)會(huì)話管理和token認(rèn)證的示例代碼的文章就介紹到這了,更多相關(guān)Redis 會(huì)話管理和token認(rèn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Redis實(shí)現(xiàn)分布式鎖的原理

    詳解Redis實(shí)現(xiàn)分布式鎖的原理

    分布式鎖,即分布式系統(tǒng)中的鎖,在單體應(yīng)用中我們通過(guò)鎖解決的是控制共享資源訪問(wèn)的問(wèn)題,而分布式鎖,就是解決了分布式系統(tǒng)中控制共享資源訪問(wèn)的問(wèn)題,本文講給大家詳細(xì)介紹一下Redis實(shí)現(xiàn)分布式鎖的原理,需要的朋友可以參考下
    2023-09-09
  • Redis解決緩存雪崩、穿透和擊穿的問(wèn)題(Redis使用必看)

    Redis解決緩存雪崩、穿透和擊穿的問(wèn)題(Redis使用必看)

    這篇文章主要給大家介紹了Redis解決緩存雪崩、緩存穿透、緩存擊穿的解決方案,文中有詳細(xì)的圖文介紹,具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-08-08
  • redis使用skiplist跳表的原因解析

    redis使用skiplist跳表的原因解析

    經(jīng)常會(huì)有人問(wèn)這個(gè)問(wèn)題,redis中為什么要使用跳表?這個(gè)問(wèn)題,redis作者已經(jīng)給出過(guò)明確答案,今天通過(guò)本文再給大家講解下這個(gè)問(wèn)題,對(duì)redis?skiplist跳表知識(shí)感興趣的朋友一起看看吧
    2022-10-10
  • Redis之緩存擊穿、穿透、雪崩問(wèn)題及處理

    Redis之緩存擊穿、穿透、雪崩問(wèn)題及處理

    文章詳細(xì)介紹了緩存擊穿、緩存穿透和緩存雪崩的概念、觸發(fā)條件、典型場(chǎng)景、可能后果及解決策略,強(qiáng)調(diào)了緩存設(shè)計(jì)中需考慮的多個(gè)方面,包括緩存策略、系統(tǒng)一致性、異常處理和優(yōu)化措施,通過(guò)合理設(shè)置TTL、使用分布式鎖、預(yù)熱緩存、邏輯過(guò)期刷新、布隆過(guò)濾器等多種方法
    2026-04-04
  • Redis教程之代理ip池設(shè)計(jì)方法詳解

    Redis教程之代理ip池設(shè)計(jì)方法詳解

    這篇文章主要介紹了Redis實(shí)現(xiàn)代理ip池的設(shè)計(jì)方法,文中給出了詳細(xì)的介紹與示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友們下面來(lái)一起看看吧。
    2017-01-01
  • Redis+攔截器實(shí)現(xiàn)接口防刷

    Redis+攔截器實(shí)現(xiàn)接口防刷

    接口防刷有很多種實(shí)現(xiàn)思路,例如:攔截器/AOP+Redis、攔截器/AOP+本地緩存、前端限制等等很多種實(shí)現(xiàn)思路,本文主要來(lái)講一下?攔截器+Redis?的實(shí)現(xiàn)方式,需要的可以參考下
    2023-08-08
  • 基于Redis+Lua腳本的分布式全局令牌桶限流方案

    基于Redis+Lua腳本的分布式全局令牌桶限流方案

    這篇文章主要介紹了如何采用Redis和Lua腳本實(shí)現(xiàn)分布式全局令牌桶限流,解決多實(shí)例部署、并發(fā)超賣(mài)及限流一致性問(wèn)題,保障高并發(fā)場(chǎng)景下流量控制與系統(tǒng)穩(wěn)定性,需要的朋友可以參考下
    2026-05-05
  • redis?消息隊(duì)列完成秒殺過(guò)期訂單處理方法(一)

    redis?消息隊(duì)列完成秒殺過(guò)期訂單處理方法(一)

    這篇文章主要介紹了redis?消息隊(duì)列完成秒殺過(guò)期訂單處理方法,包括redis?消息通知處理代金券過(guò)期問(wèn)題–失效問(wèn)題的分析,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Redis高效率原因及數(shù)據(jù)結(jié)構(gòu)分析

    Redis高效率原因及數(shù)據(jù)結(jié)構(gòu)分析

    這篇文章主要為大家詳細(xì)的介紹了Redis高效的原因以及分析了Redis高效的數(shù)據(jù)結(jié)構(gòu),有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • Redis下載與安裝全過(guò)程(Windows版)

    Redis下載與安裝全過(guò)程(Windows版)

    這篇文章詳細(xì)介紹了如何在Windows系統(tǒng)上安裝和配置Redis,包括下載、安裝步驟、配置服務(wù)、啟動(dòng)和停止服務(wù)以及基本測(cè)試方法,同時(shí),還解決了一些常見(jiàn)的連接問(wèn)題,如外部服務(wù)器連接失敗
    2026-02-02

最新評(píng)論

左云县| 天等县| 工布江达县| 沧州市| 泾源县| 佛山市| 手游| 曲沃县| 万安县| 江门市| 临漳县| 安仁县| 宁海县| 上蔡县| 黄龙县| 竹山县| 偃师市| 建平县| 田阳县| 隆林| 翁牛特旗| 金门县| 鹤岗市| 太仆寺旗| 五常市| 涡阳县| 白山市| 察隅县| 永平县| 阿拉善左旗| 弥渡县| 桃江县| 哈尔滨市| 清水县| 江津市| 博客| 永仁县| 东丰县| 滦平县| 屏南县| 普格县|