• 【Spring】借Spring MVC实现透明鉴权


    1. 前言

    1.1. 什么是透明鉴权?

    开发业务代码的时候,不用关心请求自己接口的用户是否合法。鉴权的工作交给架构中的公共代码,自己仅专心于业务实现。

    @Controller
    public class ThreadLocalController {
        
        @Autowired
        BankAccountService service;
        
        @RequestMapping("/bank/account")
        public ModelAndView doSomething(@RequestParam("id") Long id) {
        	// 省略了userService.getUserById() 的鉴权操作,也不用在方法上增加一个userId参数
            service.doSomething();
            return new ModelAndView();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.2. 有什么好处?

    践行 “单一职责” 原则。鉴权与授权都应该是安全模块的内容,当单体架构膨胀到一定程度后,考虑重构为微服务时,安全模块可拔插的特点就有优势了。

    1.3. 透明鉴权后,还有什么需要考虑的?

    • 细粒度控制依旧在业务层
      EG: 删除客户资源,要取登录人的信息确保是本人删除

    • ThreadLocal 的技术抉择
      EG: ThreadLocal 用来存储上下文中用户实体,避免User参数层层传递,但是在线程池环境下,ThreadLocal很容易出问题。Spring Cloud Hystrix 默认Thread隔离,要修改成Semaphore才能避免 ThreadLocal 污染。

    • 授权与鉴权的兼容
      EG: 用户获得新的权限,旧的token如何处理(强制下线重新登录还是做兼容)

    1.4. 本文的重点是什么?

    • 理清Servlet FilterSpring MVC Interceptor 的能力边界
    • 构建一个透明鉴权的模型,可迁移到Spring Cloud GatewaySpring Security的学习中

    2. 一个简单的鉴权流程图

    在这里插入图片描述

    2.1. 基本思想

    • Filter 能有读取header的能力,根据token是否携带、token是否命中缓存(缓存可以是Session/ConcurrentHashMap/Redis) 转发给对应的url,让Spring的DispatcherServlet接管
      • 缺少token => /token/empty => 返回401
      • token失效 => /token/invalid => 返回403
    • 有效的token会正常进入Spring 的 Controller,这样在Controller层就不用校验用户是否合法了

    2.2. 不足与思考

    后端接口不需要校验请求的合法性,但是需要请求人的信息时怎么办?
    —— 在Filter层访问缓存时,提供一个获取user实体的能力

    • 用户登录写入token - user实体
    • 用户带着token访问,用token获取user实体
    • 在Filter层 把user实体放入threadlocal,让 controller后的代码能获取到user实体
    • 用户信息修改,把缓存的token及user实体清除,确保一致性

    3. 引入ThreadLocal 的流程图

    在这里插入图片描述

    3.1. 不足与思考

    • ThreadLocal 很容易造成内存泄漏
      使用Spring mvc 的 Interceptor 进行后置处理,remove掉ThreadLocal

    4. 引入Interceptor 的流程图

    在这里插入图片描述

    5. 后记

  • 相关阅读:
    北理工嵩天Python语言程序设计笔记(6 函数和代码复用)
    【自然语言处理】Python基于逻辑回归模型进行电影评论情感分析项目实战
    论文阅读 Continuous-Time Dynamic Network Embeddings
    Typescript 回调函数、事件侦听的类型定义与注释--拾人牙慧
    数据结构:平衡二叉树
    抖音seo矩阵系统源码开发开源型私有化部署方案
    Java扩展Nginx之三:基础配置项
    Django Form实现表单使用及应用场景
    vue 获取上一周和获取下一周的日期时间
    js闭包深入理解(Closure)
  • 原文地址:https://blog.csdn.net/chenghan_yang/article/details/125561250