Session神奇的過期

NO IMAGE
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

初衷&緣起

最近在構思一件事情,使用spring-boot spring-security oauth實現授權的demo;
要測試,動手敲程式碼最實際,但是,思考也是不能少的,否則也只是複製貼上程式碼。

測試oauth的第一步,肯定是先弄明白怎麼請求授權伺服器,怎麼拿到code再拿到token。
所以第一步是建立一個能使用的“client”。通過對比,微博開放平臺會相對簡單點,因為微信有環境的限制。

在閱讀微博開放平臺的登入授權介面時,發現要填寫一個授權的回撥url。
那麼疑問就來了:
如果我的“client”應用是一個類似公眾號的
比如:有多個選單,點選跳到不同的頁面,而這些頁面都需要先登入微博授權
限制:使用者點選登入授權之後,回撥的url是同一個
結果:那不管點選那個選單,最後都是跳到回撥的頁面,多個選單就形同虛設了

請求過程分析

請注意,這裡不是分析如何授權登入,而是授權成功時,如何跳到所點選的入口(選單)

假設(靜默授權,就是不需要使用者點選確認):

  • 我們的應用(client)的域名是:web.client.com
  • client中有一個選單是:web.client.com/ha
  • client中有個回撥地址:web.client.com/receive
  • 微博開發平臺的域名是:oauth.server.com
  • 微博確認授權介面地址是:oauth.server.com/test

過程:

  • 訪問client的任意選單(web.client.com/ha)
  • client發現需要登入微博授權,將使用者重定向到oauth.server.com/test
  • 微博確認了使用者資訊,把使用者重定向到web.client.com/receive,並帶上code
  • client接收到code,並且可以通過code拿到token並暫存。

問題在於:最後一步,拿到code再拿到token後,如何跳到我們所點選的入口(選單)

猜測&實驗:session能否實現?

猜測思路

session存放我們所點選的入口(選單),在接收code的回撥介面中,在把使用者重定向到我們所點選的入口選單。

實驗程式碼

host配置兩個站點

127.0.0.1 oauth.server.com
127.0.0.1 web.client.com

web.client.com介面

package com.lgh.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Controller
public class IndexController {

    @RequestMapping("/ha")
    public String index(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception {
        System.out.println("/ha 請求,redirect:http://oauth.server.com/test");
        System.out.println(session.getId());
        System.out.println(request.getRequestURL());
        session.setAttribute("entrance", request.getRequestURL());
        return "redirect:http://oauth.server.com/test";
    }

    @RequestMapping("ha2")
    public String index2(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception {
        System.out.println("/ha2 請求,redirect:http://oauth.server.com/test");
        System.out.println(session.getId());
        System.out.println(request.getRequestURL());
        session.setAttribute("entrance", request.getRequestURL());
        return "redirect:http://oauth.server.com/test";
    }

    @RequestMapping("/receive")
    public String receive(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
        System.out.println("/receive請求, 返回haha.jsp");
        System.out.println(session.getId());
        System.out.println("code = "   request.getParameter("code"));
        System.out.println("入口地址:"   session.getAttribute("entrance"));
        return "haha";
    }
}

oauth.server.com介面(php)

<?php
session_start();
$code = rand(10000, 99999);
header("Location: http://web.client.com:8080/receive?code=$code");
exit;
?>

實驗結果

第一次:web.client.com:8080/ha

第二次:web.client.com:8080/ha2

注意在測試兩個介面的中間,要徹底關閉瀏覽器,否則拿到的session是沒變的

再來思考下session的過期和時效

  • 過期:一般會有預設的過期時間,是由伺服器的預設配置的。
  • 失效:一般都是瀏覽會話結束時失效(瀏覽會話結束是指:瀏覽器徹底關掉所有的tab,一個不留,有一個沒關,瀏覽會話都沒結束)

腦殘測試

條件

  • 把client的兩個介面都設定session的過期時間:session.setMaxInactiveInterval(2);
  • server介面中,新增睡眠程式碼:sleep(10);

結果

由於session都過期了,server才返回code,此時拿到的session自然沒有東西啦

延伸思考:

多次訪問不同入口

如果真的是多個選單的場景,會存在一種情況:我點了一個選單,退出來,再點第二個選單,session存的入口選單就會覆蓋,這種情況會不會有問題?

分析:
不同時刻關閉重新點選選單,造成的影響會有點點不一樣
如果我們在拿到token之後,在session裡存放使用者的標誌欄位,在其他入口地址根據是否存在使用者的標誌欄位來判斷是否需要重新認證,就沒問題了。

相關文章

程式語言 最新文章