Spring Security认证成功后回跳(解决前后端分离下OAuth2认证成功回跳)

2023-11-03

前言

Spring Security(后面简称SS)用了很长时间了,但之前一直没注意到一个有趣的特性,直到最近弄前后端分离,在OAuth2提供者(github)认证后,需要跳回前端页面(前端页面和服务端不在同个域下),然后突然一般情况下(同域),SS认证后会自动跳回认证前用户想访问的资源。由此开始寻找这个magic。

OAuth2 的一个sso demo,有兴趣可以看一下

问题:SS是怎么在认证成功后自动跳转到认证前用户想访问的资源(url)?

原本我以为SS是跟SS OAuth的实现一样,通过在http报文里面传递这个url,但是看浏览器的报文内容,在认证过程中是没有传递过url的。而且在OAuth里面,OAuth2 provider这种第三方服务,不可能帮你传递这个参数,所以比较好的办法就是利用session,这也解释前后端分离情况下,SS不会(不能)帮我们跳回去前端页面

问题的切口:SavedRequestAwareAuthenticationSuccessHandler

之前我用SS经常接触到这个类,但是我只知道它作为认证成功的handler,在认证成功后会进行一个跳转操作。这里是部分源码

public class SavedRequestAwareAuthenticationSuccessHandler extends
        SimpleUrlAuthenticationSuccessHandler {
    protected final Log logger = LogFactory.getLog(this.getClass());

    private RequestCache requestCache = new HttpSessionRequestCache();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication)
            throws ServletException, IOException {
        //这里取出了一个request
        SavedRequest savedRequest = requestCache.getRequest(request, response);

        if (savedRequest == null) {
            super.onAuthenticationSuccess(request, response, authentication);

            return;
        }
        String targetUrlParameter = getTargetUrlParameter();
        if (isAlwaysUseDefaultTargetUrl()
                || (targetUrlParameter != null && StringUtils.hasText(request
                        .getParameter(targetUrlParameter)))) {
            requestCache.removeRequest(request, response);
            super.onAuthenticationSuccess(request, response, authentication);

            return;
        }

        clearAuthenticationAttributes(request);

        // Use the DefaultSavedRequest URL !!关键的一句!!
        String targetUrl = savedRequest.getRedirectUrl();
        logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
        // 这里有一个很明显的跳转操作,追踪targetUrl怎么来的
        getRedirectStrategy().sendRedirect(request, response, targetUrl);
    }

    public void setRequestCache(RequestCache requestCache) {
        this.requestCache = requestCache;
    }
}

这里有一个很奇怪的属性——savedRequest,从上面就可以看到,它是来自requestCacherequestCache的类型是HttpSessionRequestCache。这里可以看到,第一行代码就从requestCachegetRequest方法中取出了savedRequest,看一下这个方法

public SavedRequest getRequest(HttpServletRequest currentRequest,
            HttpServletResponse response) {
        HttpSession session = currentRequest.getSession(false);

        if (session != null) {
            return (SavedRequest) session.getAttribute(SAVED_REQUEST);
        }

        return null;
    }

这里就印证了我们前面的猜测,的确是保存在session里面,那么SS什么时候放进去的?毕竟我想要前后端分离下OAuth2认证后跳回前端页面

很容易猜测是调用HttpSessionRequestCachesetRequest方法放进去,可以搜索,这里我是用上面的sso demo的日志找到ExceptionTranslationFiltersendStartAuthentication方法(把日志级别调到debug)

ExceptionTranslationFilter

ExceptionTranslationFilter源码里面注释的第一句话就说明了它的用处

Handles any AccessDeniedException and AuthenticationException
thrown within the filter chain.

这里也解释了各种认证filter诸如UsernamePasswordAuthenticationFilter为什么可以随便抛出AuthenticationException

protected void sendStartAuthentication(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain,
            AuthenticationException reason) throws ServletException, IOException {
        // SEC-112: Clear the SecurityContextHolder's Authentication, as the
        // existing Authentication is no longer considered valid
        SecurityContextHolder.getContext().setAuthentication(null);
        requestCache.saveRequest(request, response);
        logger.debug("Calling Authentication entry point.");
        authenticationEntryPoint.commence(request, response, reason);
    }

到这里大概明白了SS怎么保存和跳转回认证前用户想访问的资源,总结一下。SS通过ExceptionTranslationFilter在认证开始前把request缓存到session中,当认证成功后,在SavedRequestAwareAuthenticationSuccessHandler里取出缓存的request,跳转回认证前用户想访问的url

解决前后端分离下OAuth2认证后跳回前端页面

理解了SS怎么处理认证成功自动跳转问题,解决前后端分离下OAuth2认证成功跳转就很容易了。这里先说一下前后端跨域下OAuth2认证的流程(OAuth2协议具体请自己谷歌,我也说不清楚)

oauth2.png

这个流程比同域OAuth2情况下少了一步,同域下第一步应该是访问一个受保护资源,然后才开始上面流程,所以我暂时的做法是

在/login接口处接受一个auth_url参数,表示认证成功后跳转到这个url,然后认证成功后取出这个url进行跳转

这样只需要修改两处地方

继承OAuth2ClientAuthenticationProcessingFilter

class MyOAuth2ClientAuthenticationProcessingFilter extends OAuth2ClientAuthenticationProcessingFilter{

        private RequestCache requestCache = new HttpSessionRequestCache();

        public MyOAuth2ClientAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
            super(defaultFilterProcessesUrl);
        }

        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
            requestCache.saveRequest(request, response);
            return super.attemptAuthentication(request, response);
        }
    }

重写这个filter的AuthenticationSuccessHandler

filter.setAuthenticationSuccessHandler((request, response, authentication) -> {
            String authUrl = request.getParameter("auth_url");
            response.sendRedirect(authUrl);
        });

这样就简单粗暴地实现了OAuth2下认证成功后可以自动跳转回认证前想访问的资源了。



作者:zerouwar
链接:https://www.jianshu.com/p/39f46c8de9c1
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Security认证成功后回跳(解决前后端分离下OAuth2认证成功回跳) 的相关文章

  • DOS命令(windows)

    DOS命令 windows 目录 1 打开命令提示符 2 切换至根 3 当前路径 4 切换至上级路径 5 查看当前目录 6 查看文件内容 7 删除文件 8 进入长文件夹名时缩写 9 复制文件 10 移动文件 1 打开命令提示符 命令 win
  • 【opencv】Python-OpenCV自学自用笔记-上篇

    前言 本文是我在学习opencv时记录的笔记 内容较为简洁 会记录从入门到做项目这段时间的内容 最终目的是完成我的毕业设计 欢迎大家给予批评指正 本篇为第一本书 Python OpenCV从入门到精通 的笔记 前两章为安装 略过 第六章到第
  • 基于Jekyll创建免费的静态博客站点

    完整版请参考 https mazhaoxin github io 2018 08 04 Create Free Static Blog Base On Jekyll http 483v7j coding pages com 2018 08
  • JavaScript & ES6 部分面试题汇总

    1 js数据类型有哪些 基本类型 字符串 String 数字 Number 布尔 Boolean 空 Null 未定义 Undefined Symbol 唯一值 引用类型 对象 Object 数组 Array 函数 Function Set
  • 在Form窗体中,this的应用

    背景 在BHHT Bill界面中点击某个按钮时 弹出BHZX界面 并在BHZX界面中输入值 然后将BHZX界面中输入的值传递回BHHT Bill界面 在BHHT Bill界面中 属性 public string vsBZ string Em
  • Seaborn的使用以及调色板的设置

    Seaborn的使用以及调色板的设置 1 Seaborn简介 Seaborn是基于Python并且非常受欢迎的图形可视化库 并且在matplotlib的基础上进行了更高级的封装 使用作图更加方便快捷 可以通过极简的代码做出十分具有价值并且非
  • 【网络安全带你练爬虫-100练】第23练:文件内容的删除+写入

    目录 0x00 前言 0x02 解决 0x00 前言 本篇博文可能会有一点点的超级呆 0x02 解决 你是不是也会想 使用pyrhon将指定文件夹位置里面的1 txt中数据全部删除以后 gt 然后再将参数req text的值写入到1 txt
  • 前端小白HTML——1.html基础

    HTML语言的基本规则 1 1 HTML基本结构 内是头部信息 不显示在网页上 内是网页内容
  • vs2019断点调试设置断点条件

    系列文章目录 文章目录 系列文章目录 前言 一 使用条件断点 二 使用步骤 1 示例代码 前言 使用vs2019调试代码时 如果遇到for while do while逊汗语句时 而且循环次数很多时 改怎么办呢 一 使用条件断点 二 使用步
  • Ubuntu18.04使用阿里源镜像安装Docker并配置镜像加速【图文详细】

    官方安装文档 https docs docker com engine install ubuntu 阿里源安装文档 推荐 https developer aliyun com mirror docker ce spm a2c6h 1365
  • Unable to build Cython components. Please make sure Cython is installed if the torch.hub

    在我使用torch hub的时候报了如下一个错误 解决方法 参考 https github com h5py h5py issues 535 先安装 h5py 再安装 Cython pip install h5py pip install
  • 概率论中高斯分布(正态分布)介绍及C++11中std::normal_distribution的使用

    高斯分布 最常用的分布是正态分布 normal distribution 也称为高斯分布 Gaussian distribution 正态分布N x 2 呈现经典的 钟形曲线 的形状 其中中心峰的x坐标由 给出 峰的宽度受 控制 正态分布由
  • c++ 提取字符串前面数字stoi和atoi

    stoi和atoi 包含在 include lt cstdlib gt 作用是将字符串转化为int型 区别是stoi的形参是string 而atoi的形参是char 注 只是将字符串前面是数字的部分提取出来 代码可以看这篇文章 https
  • ChatGPT无限卡Cloudflare 验证你是真人

    问题 我的情况是这样 在Chrome里 打开chatGPT的网页 会无限验证你是真人 打开无痕浏览页面可以正常登录 2023 04 20 更新 新的解决方案 github上有一个油猴脚本 KeepChatGPT 可以解决这个问题 至少目前我
  • 02Tcpdump命令详解-网络抓包工具

    1 概述 今天我们要介绍的是一款网络抓包工具tcpdump 重点讨论并介绍一些有用的命令及最佳实践 tcpdump是一个功能最强大 应用最广泛的命令行数据包嗅探器或包分析工具 用于抓取或过滤制定接口接受或发送的TCP IP数据包 tcmpd
  • 42-Docker-Docker命令详解-docker build

    Docker命令详解 docker build 前言 docker build 原理 语法格式 options说明 使用示例 前言 本篇来学习下制作docker镜像的命令 docker build docker build 原理 docke
  • 环境文件复制

    1 yaml复制 package com ybw yaml demo generate import com alibaba fastjson2 JSON import lombok extern slf4j Slf4j import or

随机推荐

  • linux android studio 快捷方式,Android Studio 使用小技巧和快捷键

    Android Studio 使用小技巧和快捷键 Published by xiaosixi on 2016年12月19日 1 书签 Bookmarks 描述 这是一个很有用的功能 让你可以在某处做个标记 书签 方便后面再跳转到此处 调用
  • 【论文速览】ICLR23 - 将图像视为一组点集 Image as Set of Points

    文章目录 研究背景 解决思路 部分实验效果 思考 参考资料 收录于ICLR2023 oral notable top 5 代码地址 https github com ma xu Context Cluster 研究背景 目前计算机视觉领域最
  • 循环代码模型构建方法

    循环结构是源代码程序的重要结构 然而即使是简单的循环程序 也很容易出错 循环中的很多错误往往需要执行多次或者在某些特定的情况下才能被发现 检测这些错误的代价很高 所以需要重点开展对软件循环代码的安全性分析研究 而对循环代码结构进行研究的重要
  • 2018年Android面试题含答案--适合中高级

    1 java中 和equals和hashCode的区别 基本数据类型的 比较的值相等 类的 比较的内存的地址 即是否是同一个对象 在不覆盖equals的情况下 同比较内存地址 原实现也为 如String等重写了equals方法 hashCo
  • 如何学会读论文?送你滑铁卢大学S. Keshav的三轮阅读法

    来源 专知 本文约3100字 建议阅读6分钟 本文为你介绍三轮阅读法 教你如何高效读论文 导读 读论文是从事科学研究与工程等必不可少环节 但是如何高效读论文却有一番讲究 滑铁卢大学S Keshav 撰写了 How to Read a Pap
  • 80 后女程序员拒当「码农」:“转行小说家后,我用 AI 写了 16 本书!”

    省时查报告 专业 及时 全面的行研报告库 省时查方案 专业 及时 全面的营销策划方案库 免费下载 2023年8月份全网热门报告合集 ChatGPT提词示例 让你的ChatGPT聪明100倍 超百页干货资料 AI应用的难点 痛点与未来 202
  • 终止关闭服务端口号 8080为例

    Identify and stop the process that s listening on port 8080 or configure thi 当我们遇到服务器端口号被占用的时候 下一个服务器就带不开了 让人很是烦躁 下面猿猿总结
  • 【华为OD机试真题 python】事件推送【2022 Q4

    题目描述 事件推送 同一个数轴X上有两个点的集合A A1 A2 Am 和B B1 B2 Bn Ai和Bj均为正整数 A B已经按照从小到大排好序 A B均不为空 给定一个距离R 正整数 列出同时满足如下条件的所有 Ai Bj 数对 1 Ai
  • oracle单实例客户端连接的failover功能

    今天测试了一下单实例数据库客户端连接的failover功能 操作系统为red hat 5 5 root localhost cat etc issue Red Hat Enterprise Linux Server release 5 5
  • vue项目树状图的实现

    1 实现背景 项目需要直观的展示元素之间的关系 需要实现一个树状图 数据可视化可以用Echarts HighCharts 但是相关树状图的示例不够直观 且不美观 几种工具之间比较 选择了蚂蚁金服的G6来实现 在开发期间有树状图的示例 之后再
  • 快速排序基本思想及代码实现-史上最通俗易懂的

    来源 我是码农 转载请保留出处和链接 本文链接 http www 54manong com id 1236 1 算法思想 快速排序是C R A Hoare于1962年提出的一种划分交换排序 它采用了一种分治的策略 通常称其为分治法 Divi
  • MQTT遗愿(last will) paho.mqtt实现

    一 MQTT遗嘱 MQTT 可以设置遗嘱 客户端在连接Broker的时候将遗嘱内容 也是topic payload形式 遗嘱也有一个主题 发送给Broker并保存在Broker中 当客户端因为非正常原因断开与Broker的连接时 Broke
  • 进程的相概念(linux系统编程)

    什么是程序 什么是进程 有什么区别 程序是静态的概念 gcc xx x o pro 磁盘中生成的pro就是程序 进程是程序的一次运行活动 通俗的讲就是程序跑起来了 系统中就多了一个进程 在Linux里面怎么查看系统中有哪些进程 使用ps指令
  • linux的超级管理用户

    超级管理用户 也称为root用户 是Linux系统中最高权限用户 root用户具有完全控制系统的权限 可以执行任何操作 包括管理文件 修改配置 安装软件等 下面是root用户的用法大全 切换到root用户 在终端中输入以下命令 su roo
  • 青龙面板使用教程,以及安装

    1 青龙面板使用教程 以及安装 首先青龙面板是在docker里面的 我们要安装一个docker 我这里只有debian 11 安装的教程 如何在debian11上安装docker 知乎 这个文章不错了 按命令执行就好了 其他操作系统的 去网
  • K8S-11--prometheus--(监控基础/prometheus基础/grafana/promQL/exporter/cadvisor)

    一 监控基础 一 监控简介 监控模型 端监控 业务层监控 应用层监控 中间件监控 系统层监控 1 监控概述 web监控 打开速度 URL打开状态码 API接口可用性 业务监控 订单交易量 活跃用户量 支付量 中间件监控 数据库 redis
  • 跳出ping++退款的坑

    近期在项目的开发过程中 需要用到ping 的退款功能 由于使用的版本比官方提供的要低2个小版本 因此问题并不是很大 但是由于官方文档有些内容写的比较含蓄 因此遇到了一些问题 我们可以通过如下的方式来获取SDK的版本 gt gt gt imp
  • STM32开发环境配置相关问题记录

    1 编译时出现 error 35 error directive Please select first the target STM32F10x device used 解决方案 点选options for target 选择C C 在d
  • K8S deployment挂载

    Deployment部署文件 apiVersion apps v1 kind Deployment metadata annotations deployment kubernetes io revision 1 kubectl kuber
  • Spring Security认证成功后回跳(解决前后端分离下OAuth2认证成功回跳)

    前言 Spring Security 后面简称SS 用了很长时间了 但之前一直没注意到一个有趣的特性 直到最近弄前后端分离 在OAuth2提供者 github 认证后 需要跳回前端页面 前端页面和服务端不在同个域下 然后突然一般情况下 同域