国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

SpringBoot+SpringSession+Redis實(shí)現session共享及唯一登錄

發(fā)布時(shí)間:2021-07-17 21:51 來(lái)源:腳本之家 閱讀:0 作者:保爾-科查筋 欄目: 編程語(yǔ)言 歡迎投稿:712375056

最近在學(xué)習springboot,session這個(gè)點(diǎn)一直困擾了我好久,今天把這些天踩的坑分享出來(lái)吧,希望能幫助更多的人。

一、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
#超時(shí)一定要大于0
spring.redis.timeout=3000
spring.session.store-type=redis

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

三、編寫(xiě)登錄狀態(tài)攔截器RedisSessionInterceptor

//攔截登錄失效的請求
public class RedisSessionInterceptor implements HandlerInterceptor
{
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        //無(wú)論訪(fǎng)問(wèn)的地址是不是正確的,都進(jìn)行登錄驗證,登錄成功后的訪(fǎng)問(wèn)再進(jìn)行分發(fā),404的訪(fǎng)問(wèn)自然會(huì )進(jìn)入到錯誤控制器中
        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, "", "用戶(hù)未登錄!")));
        }
        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開(kāi)頭的訪(fǎng)問(wèn)都要進(jìn)入RedisSessionInterceptor攔截器進(jìn)行登錄驗證,并排除login接口(全路徑)。必須寫(xiě)成鏈式,分別設置的話(huà)會(huì )創(chuàng  )建多個(gè)攔截器。
        //必須寫(xiě)成getSessionInterceptor(),否則SessionInterceptor中的@Autowired會(huì )無(wú)效
        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, "賬戶(hù)名或密碼錯誤!");
        }
    }
 
    @RequestMapping(value = "/getUserInfo")
    public ReturnData get(long userId)
    {
        User user = userService.findUserByUserId(userId);
        if (user != null)
        {
            return new ReturnData(StatusCode.REQUEST_SUCCESS, user, "查詢(xún)成功!");
        }
        else
        {
            throw new MyException(StatusCode.USER_NOT_EXIST, "用戶(hù)不存在!");
        }
    }
}

六、效果

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

瀏覽器:

postman:

七、核心原理詳解

分布式session需要解決兩個(gè)難點(diǎn):1、正確配置redis讓springboot把session托管到redis服務(wù)器。2、唯一登錄。

1、redis:

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

同時(shí)還要保證配置正確

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

springboot啟動(dòng)后能在redis上查到緩存的session才能說(shuō)明整個(gè)redis+springboot配置成功!

2、唯一登錄:

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

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

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

唯一登錄經(jīng)過(guò)我的驗證后滿(mǎn)足需求,暫時(shí)沒(méi)有出現問(wèn)題,也希望大家能看看有沒(méi)有問(wèn)題,有的話(huà)給我點(diǎn)好的建議!

到此這篇關(guān)于SpringBoot+SpringSession+Redis實(shí)現session共享及唯一登錄示例的文章就介紹到這了,更多相關(guān)SpringBoot 唯一登錄內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。

首页+国产+亚洲+丝袜图片区| 粉嫩大学生无套内射无码卡视频| 在线播放无码后入内射少妇| 亚洲熟妇丰满XXXXX国语| 被伴郎的内捧猛烈进出H| 亚洲无人区天空码头IV在哪|