溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot+SpringSession+Redis怎么實現session共享

發布時間:2021-04-30 10:09:36 來源:億速云 閱讀:313 作者:小新 欄目:開發技術

這篇文章主要介紹SpringBoot+SpringSession+Redis怎么實現session共享,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

springboot是什么

springboot一種全新的編程規范,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程,SpringBoot也是一個服務于框架的框架,服務范圍是簡化配置文件。

一、pom.xml配置 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
 
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

二、application.properties的redis配置

#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=123456
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
#超時一定要大于0
spring.redis.timeout=3000
spring.session.store-type=redis

在配置redis時需要確保redis安裝正確,并且配置notify-keyspace-events Egx,spring.redis.timeout設置為大于0,我當時這里配置為0時springboot時啟不起來。

三、編寫登錄狀態攔截器RedisSessionInterceptor

//攔截登錄失效的請求
public class RedisSessionInterceptor implements HandlerInterceptor
{
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        //無論訪問的地址是不是正確的,都進行登錄驗證,登錄成功后的訪問再進行分發,404的訪問自然會進入到錯誤控制器中
        HttpSession session = request.getSession();
        if (session.getAttribute("loginUserId") != null)
        {
            try
            {
                //驗證當前請求的session是否是已登錄的session
                String loginSessionId = redisTemplate.opsForValue().get("loginUser:" + (long) session.getAttribute("loginUserId"));
                if (loginSessionId != null && loginSessionId.equals(session.getId()))
                {
                    return true;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
 
        response401(response);
        return false;
    }
 
    private void response401(HttpServletResponse response)
    {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
 
        try
        {
            response.getWriter().print(JSON.toJSONString(new ReturnData(StatusCode.NEED_LOGIN, "", "用戶未登錄!")));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
    {
 
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
    {
 
    }
}

四、配置攔截器

@Configuration
public class WebSecurityConfig extends WebMvcConfigurerAdapter
{
    @Bean
    public RedisSessionInterceptor getSessionInterceptor()
    {
        return new RedisSessionInterceptor();
    }
 
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        //所有已api開頭的訪問都要進入RedisSessionInterceptor攔截器進行登錄驗證,并排除login接口(全路徑)。必須寫成鏈式,分別設置的話會創建多個攔截器。
        //必須寫成getSessionInterceptor(),否則SessionInterceptor中的@Autowired會無效
        registry.addInterceptor(getSessionInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/user/login");
        super.addInterceptors(registry);
    }
}

五、登錄控制器

@RestController
@RequestMapping(value = "/api/user")
public class LoginController
{
    @Autowired
    private UserService userService;
 
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    @RequestMapping("/login")
    public ReturnData login(HttpServletRequest request, String account, String password)
    {
        User user = userService.findUserByAccountAndPassword(account, password);
        if (user != null)
        {
            HttpSession session = request.getSession();
            session.setAttribute("loginUserId", user.getUserId());
            redisTemplate.opsForValue().set("loginUser:" + user.getUserId(), session.getId());
 
            return new ReturnData(StatusCode.REQUEST_SUCCESS, user, "登錄成功!");
        }
        else
        {
            throw new MyException(StatusCode.ACCOUNT_OR_PASSWORD_ERROR, "賬戶名或密碼錯誤!");
        }
    }
 
    @RequestMapping(value = "/getUserInfo")
    public ReturnData get(long userId)
    {
        User user = userService.findUserByUserId(userId);
        if (user != null)
        {
            return new ReturnData(StatusCode.REQUEST_SUCCESS, user, "查詢成功!");
        }
        else
        {
            throw new MyException(StatusCode.USER_NOT_EXIST, "用戶不存在!");
        }
    }
}

六、效果

我在瀏覽器上登錄,然后獲取用戶信息,再在postman上登錄相同的賬號,瀏覽器再獲取用戶信息,就會提示401錯誤了,瀏覽器需要重新登錄才能獲取得到用戶信息,同樣,postman上登錄的賬號就失效了。

瀏覽器:

SpringBoot+SpringSession+Redis怎么實現session共享

SpringBoot+SpringSession+Redis怎么實現session共享

postman:

SpringBoot+SpringSession+Redis怎么實現session共享

七、核心原理詳解

分布式session需要解決兩個難點:1、正確配置redis讓springboot把session托管到redis服務器。2、唯一登錄。

1、redis:

redis需要能正確啟動到出現如下效果才證明redis正常配置并啟動

SpringBoot+SpringSession+Redis怎么實現session共享

同時還要保證配置正確

@EnableCaching
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30)//session過期時間(秒)
@Configuration
public class RedisSessionConfig
{
    @Bean
    public static ConfigureRedisAction configureRedisAction()
    {
        //讓springSession不再執行config命令
        return ConfigureRedisAction.NO_OP;
    }
}

springboot啟動后能在redis上查到緩存的session才能說明整個redis+springboot配置成功!

SpringBoot+SpringSession+Redis怎么實現session共享

2、唯一登錄:

1、用戶登錄時,在redis中記錄該userId對應的sessionId,并將userId保存到session中。

HttpSession session = request.getSession();
session.setAttribute("loginUserId", user.getUserId());
redisTemplate.opsForValue().set("loginUser:" + user.getUserId(), session.getId());

2、訪問接口時,會在RedisSessionInterceptor攔截器中的preHandle()中捕獲,然后根據該請求發起者的session中保存的userId去redis查當前已登錄的sessionId,若查到的sessionId與訪問者的sessionId相等,那么說明請求合法,放行。否則拋出401異常給全局異常捕獲器去返回給客戶端401狀態。

以上是“SpringBoot+SpringSession+Redis怎么實現session共享”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女