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

Redis優(yōu)化token校驗(yàn)主動(dòng)失效的實(shí)現(xiàn)方案

 更新時(shí)間:2024年03月25日 09:13:37   作者:前端小菜渣渣徐  
在普通的token頒發(fā)和校驗(yàn)中 當(dāng)用戶發(fā)現(xiàn)自己賬號(hào)和密碼被暴露了時(shí)修改了登錄密碼后舊的token仍然可以通過系統(tǒng)校驗(yàn)直至token到達(dá)失效時(shí)間,所以系統(tǒng)需要token主動(dòng)失效的一種能力,所以本文給大家介紹了Redis優(yōu)化token校驗(yàn)主動(dòng)失效的實(shí)現(xiàn)方案,需要的朋友可以參考下

場(chǎng)景:

在普通的token頒發(fā)和校驗(yàn)中 當(dāng)用戶發(fā)現(xiàn)自己賬號(hào)和密碼被暴露了時(shí)修改了登錄密碼后舊的token仍然可以通過系統(tǒng)校驗(yàn)直至token到達(dá)失效時(shí)間,這肯定是不安全的,所以系統(tǒng)需要token主動(dòng)失效的一種能力

解決方案:

我們可以使用redis來實(shí)現(xiàn)redis主動(dòng)失效的的功能

需求實(shí)現(xiàn)邏輯:

在每次用戶登錄后頒發(fā)token的同時(shí)往redis數(shù)據(jù)庫中存儲(chǔ)一份頒發(fā)給用戶的token
每次每次用戶請(qǐng)求時(shí)除了解析token外還需要查詢r(jià)edis中是否有當(dāng)前token有則校驗(yàn)通過,沒有則校驗(yàn)失敗
每次用戶修改密碼后刪除redis中當(dāng)前用所攜帶的token,從而使舊token無法通過token校驗(yàn)

代碼實(shí)現(xiàn)

pom.xml中添加redis坐標(biāo)

<!--redis坐標(biāo)-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>

配置文件application.yml中配置redis相關(guān)信息

spring:
  data:
    redis:
      host: redis所在的ip,本機(jī)的redis服務(wù)填localhost
      port: redis服務(wù)端口,默認(rèn)6379
      password: redis中設(shè)置的密碼,沒有就不需要

頒發(fā)token時(shí)往redis中存儲(chǔ)token

//UserController中添加私有屬性stringRedisTemplate并實(shí)例化
@Autowired
private StringRedisTemplate stringRedisTemplate;

//登錄接口中把token存到redis 過期時(shí)間3小時(shí)
stringRedisTemplate.opsForValue().set(token,token,3, TimeUnit.HOURS);

登錄時(shí)校驗(yàn)是否redis中有當(dāng)前token

package org.example.intercopters;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.example.utils.JwtUtil;
import org.example.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;

@Component //注冊(cè)攔截器 將其放入ioc容器中
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private StringRedisTemplate redisTemplate;
    //創(chuàng)建登錄身份校驗(yàn)攔截器
    @Override  //請(qǐng)求開始前觸發(fā)的攔截方法
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //令牌驗(yàn)證
        String token = request.getHeader("Authorization");
        //去除token的前綴標(biāo)記"Bearer "
        var newToken = token.contains("Bearer ")?token.substring("Bearer ".length()):token;

        try {
            **//從redis獲取相同的token
            String redisToken = redisTemplate.opsForValue().get(newToken);
            if(redisToken == null){
                //redis失效
                throw new RuntimeException("token失效");
            }**
            Map<String, Object> claims = JwtUtil.parseToken(token);

            //把用戶信息存儲(chǔ)到ThreadLocal中,tomcat會(huì)在每次接口請(qǐng)求時(shí)創(chuàng)建一個(gè)線程 而ThreadLocal中存儲(chǔ)的數(shù)據(jù)是線程安全的
            ThreadLocalUtil.set(claims);

            //放行
            return true;

        } catch (Exception e) {
            //設(shè)置響應(yīng)狀態(tài)碼
            response.setStatus(401);
            //設(shè)置響應(yīng)字符集和響應(yīng)內(nèi)容
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html; charset=UTF-8");
            String errorMessage = "未登錄";
            response.getWriter().write("{\"error\": \"" + errorMessage + "\"}");
            //不放行
            return false;
        }
    }
    @Override  //請(qǐng)求完成后觸發(fā)的攔截方法
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清空ThreadLocal中的數(shù)據(jù)
        ThreadLocalUtil.remove();
    }
}

修改密碼后刪除redis中的token

//修改密碼接口中刪除redis中對(duì)應(yīng)的token
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.getOperations().delete(newToken);

在本地開發(fā)中如果使用本地redis每次開發(fā)前還得去啟動(dòng)本地redis,就很麻煩,如果你有一個(gè)云服務(wù)器就可以本地連云服務(wù)器redis就不用每次去啟動(dòng)redis了,下面是實(shí)現(xiàn)教程:

前提是讀者已經(jīng)安裝好了Redis。

因?yàn)閯倢W(xué)Linux不久,敲過一些命令,算不上熟悉,對(duì)網(wǎng)絡(luò)防火墻那一塊也不熟悉。

因此雖然在項(xiàng)目中已經(jīng)開啟了Redis服務(wù),也寫好配置類:

#redis
spring.redis.host=x.x.x.x
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
```java
@Configuration
@EnableCaching  // 開啟緩存處理,使用redis,將字典的數(shù)據(jù)緩存到其中!
public class RedisConfig {
    private RedisCacheManager build;

    /**
     * 自定義key規(guī)則
     *
     * @return
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 設(shè)置RedisTemplate規(guī)則
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解決查詢緩存轉(zhuǎn)換異常的問題
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修飾符范圍,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,比如String,Integer等會(huì)跑出異常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //序列號(hào)key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 設(shè)置CacheManager緩存規(guī)則
     *
     * @param factory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解決查詢緩存轉(zhuǎn)換異常的問題
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // 配置序列化(解決亂碼的問題),過期時(shí)間600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

}

但還是啟動(dòng)不了。

在這里梳理一下:

  • 你先要去云服務(wù)器(這里以騰訊云為例)到防火墻里面添加端口,我就以默認(rèn)的6379為例。

  • 然后去你的linux上面查看你的防護(hù)墻有沒有打開和防火墻有沒有添加對(duì)應(yīng)的端口號(hào)。命令如下
#查看linux上面防火墻的狀態(tài)
systemctl status firewalld.service
#如果是running的,就需要關(guān)了
systemctl stop firewalld.service
[root@VM-4-12-centos ~]# firewall-cmd --query-port=6379/tcp#查詢
no
[root@VM-4-12-centos ~]# firewall-cmd --add-port=6379/tcp#添加
success

  • 最后你還需要去你的redis.conf文件查看你的保護(hù)有沒有打開,默認(rèn)的端口號(hào)有沒有注釋掉:
    做以下的修改,你就可以通過你的項(xiàng)目連接到Redis。
# bind 127.0.0.1 ::1
protected-mode no
port 6379

到此這篇關(guān)于Redis優(yōu)化token校驗(yàn)主動(dòng)失效的實(shí)現(xiàn)方案的文章就介紹到這了,更多相關(guān)Redis token校驗(yàn)主動(dòng)失效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis如何解決BigKey

    Redis如何解決BigKey

    在Redis的使用過程中,我們經(jīng)常會(huì)遇到BigKey, BigKey的大值會(huì)導(dǎo)致Redis內(nèi)存中產(chǎn)生大量不連續(xù)的碎片,降低內(nèi)存利用效率,本文主要介紹了Redis如何解決BigKey,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • 查看Redis內(nèi)存信息的命令

    查看Redis內(nèi)存信息的命令

    Redis 是一個(gè)開源、高性能的Key-Value數(shù)據(jù)庫,被廣泛應(yīng)用在服務(wù)器各種場(chǎng)景中。本文介紹幾個(gè)查看Redis內(nèi)存信息的命令,包括常用的info memory、info keyspace、bigkeys等。
    2020-09-09
  • Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期

    Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期

    本文主要介紹了Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期,Redisson它能給Redis分布式鎖實(shí)現(xiàn)過期時(shí)間自動(dòng)續(xù)期,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • redis中的bitmap你了解嗎

    redis中的bitmap你了解嗎

    這篇文章主要為大家詳細(xì)介紹了redis中的bitmap,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • redis分布式設(shè)計(jì)的實(shí)現(xiàn)示例

    redis分布式設(shè)計(jì)的實(shí)現(xiàn)示例

    Redis 的分布式設(shè)計(jì)主要通過三種模式實(shí)現(xiàn),每種模式解決不同的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-05-05
  • 一文弄懂Redis Stream消息隊(duì)列

    一文弄懂Redis Stream消息隊(duì)列

    本文主要介紹了一文弄懂Redis Stream消息隊(duì)列,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Redis慢查詢的具體使用

    Redis慢查詢的具體使用

    慢查詢顧名思義就是比較慢的查詢,但是究竟是哪里慢呢?本文詳細(xì)的介紹了Redis慢查詢的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-06-06
  • Redis實(shí)現(xiàn)RBAC權(quán)限管理

    Redis實(shí)現(xiàn)RBAC權(quán)限管理

    本文主要介紹了Redis實(shí)現(xiàn)RBAC權(quán)限管理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • Redis實(shí)現(xiàn)延遲任務(wù)的三種方法詳解

    Redis實(shí)現(xiàn)延遲任務(wù)的三種方法詳解

    延遲任務(wù)(Delayed Task)是指在未來的某個(gè)時(shí)間點(diǎn),執(zhí)行相應(yīng)的任務(wù),本文為大家整理了三種常見的實(shí)現(xiàn)方法,感興趣的小伙伴可以參考一下
    2025-04-04
  • redis慢查詢?nèi)罩镜脑L問和管理方式

    redis慢查詢?nèi)罩镜脑L問和管理方式

    這篇文章主要介紹了redis慢查詢?nèi)罩镜脑L問和管理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評(píng)論

西平县| 盐池县| 额尔古纳市| 茶陵县| 左云县| 合山市| 清涧县| 都安| 平阴县| 延长县| 阿城市| 资兴市| 旬阳县| 许昌县| 抚宁县| 罗江县| 滨海县| 沙田区| 赤城县| 长白| 湘西| 萝北县| 丹东市| 土默特左旗| 东至县| 沙湾县| 额敏县| 盐山县| 开封市| 碌曲县| 眉山市| 南乐县| 若尔盖县| 稷山县| 颍上县| 宜君县| 龙川县| 饶阳县| 临沧市| 阿拉尔市| 桐庐县|