Session/Cookie身份验证识别

技术派当前的用户登录信息,主要借助最基础的session/cookie来实现的;现在虽然基本进入分布式session的时代了,但切实去看oauth,sso,jwt等各种登录方案之前,有必要学习最早的cookie/session,知道他的实现方式,然后再改造项目。

Session/Cookie的基本使用

在SpringBoot项目中如何使用session/cookie

1.登录入口,保存session

首先我们设计一个登录的接口,用来模拟真实场景下的登录。

@RestController
public class SessionController{
    
    @RequestMapping(path = "/login")
    public String login(String uname ,HttpSession httpSession){

    httpSession.setAttribute("name" ,uname);
    return "欢迎登录:" + uname;
    }
 }

从上面的实现中,方法定义了一个HttpSesion的参数类型,具体实现中,就是表示写入session

当session写入完毕后,在这个会话结束之前,后续所有的请求都可以直接获取到对应的session。

2.session的读取

给出两种常见的session获取方式

直接从HttpSession中获取

通过HtttpServletRequest来获取

@RequstMapping("time")
public String showTime(HttpSssion session ){
    return sesion.getAttribute("name") + ",当前时间为: " + LocalDateTime.now();
    
    }

@RequestMapping("name")
public String showName(HttpServletRequst requst){

return "当前用户" + request.getSession.getAttribute("name");

3.退出登录

有登录当然会有登出,如下

@RequestMapping(path = "logout")
public String logout(HttpSession httpSession){
    //注销当前的session
    httpSession.invalidate();

    return "登出成功";
    }

4、session实现原理

SpringBoot提供了一套非常简单的session机制,他是如何工作的?怎样识别用户身份的?session存在什么地方?这个是我们要搞清楚的。

session:在浏览器窗口打开期间这个会话一直有效,即先访问login,在访问time,可以直接拿到name,若在此过程中,再次访问了login更新了name,那么访问time获取到的也是新的name

当浏览器关闭之后,重新访问time接口,则此时将拿不到name

核心工作原理:

借助cookie中的JESSIONID来作为用户身份标识,这个数据相同的,认为是同一个用户;然后会将session在内存中存一份,有过期时间的限制,通常每访问一次,过期时间重新刷新

当浏览器不支持cookie时,借助url重写,将sessionId写到url地址中,参数名 = jesessionid

两次的cookie中的JESSIONID是一致的。

从上面描述看,有几点关键:

session主要是存在内存中,根据用户请求cookie来识别用户身份,并且有一个过期时间(内存有大小会出现oom不)

对于用户而言,每次关闭浏览器再重新打开,会重新生成JESSIONID的cookies值,由于这个值的更改,导致后端无法记录之前访问的是谁。

技术派的身份认证

在技术派的实现中,和上面的思路没有差别,不过将读写cookie,使用session的具体逻辑,展示出来而已

当前技术派,针对前台和管理员的后台登陆,有两种,一种是基于微信公众号的,一种是传统的用户名加密码,方式不同,原理一致

具体的session/cookie的具体实例:一管理员的后台为例说明,流程为

1.登录与登出


    /**
     * 后台用户名 & 密码的方式登录
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(path = {"login"})
    public ResVo<BaseUserInfoDTO> login(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        String pwd = request.getParameter("password");
        String session = loginOutService.loginByUserPwd(username, pwd);
        if (StringUtils.isNotBlank(session)) {
            // cookie中写入用户登录信息
            response.addCookie(SessionUtil.newCookie(LoginService.SESSION_KEY, session));
            return ResVo.ok(userService.queryBasicUserInfo(ReqInfoContext.getReqInfo().getUserId()));
        } else {
            return ResVo.fail(StatusEnum.LOGIN_FAILED_MIXED, "登录失败,请重试");
        }
    }

/**
     * 登出
     *
     * @param response
     * @return
     */
    @Permission(role = UserRole.LOGIN)
    @GetMapping("logout")
    public ResVo<Boolean> logOut(HttpServletResponse response) {
        Optional.ofNullable(ReqInfoContext.getReqInfo()).ifPresent(s -> loginOutService.logout(s.getSession()));
        // 为什么不后端实现重定向? 重定向交给前端执行,避免由于前后端分离,本地开发时端口不一致导致的问题
        // response.sendRedirect("/");

        // 移除cookie
        response.addCookie(SessionUtil.delCookie(LoginService.SESSION_KEY));
        return ResVo.ok(true);
    }
 

重点关注上面的两步:

        1.根据用户,生成对应唯一session值,保存到redis缓存

        2.将session写到cookie中,返回给前端

后续用户再进行访问的时候,每次都要携带这个cookie,然后后台通过这个session来识别用户身份(所以如果这个时候cookie别别人挟持了,那么就危险了)

2.用户身份识别

接下来我们来看一看用户身份识别,核心逻辑再ReqRecordFilter

3.小结

当前技术派中的用户身份识别这套方案,与传统的cookie/session其实没有本质区别,核心思路为

  • 用户登录,生成一个唯一表示
  • 服务端保存这个唯一标识与用户的映射关系
  • 服务端将这个标识(session)写入cookie返回给客户端
  • 客户端后续请求,携带cookie

基本流程如上,重点关注相关知识点

  • 如何读写cookie
  • 如何保存用户信息(如session,如将用户标识与userId保存缓存)
  • 在filter识别完用户身份信息
  • 识别的用户身份信息,如何供整个链路使用?
  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值