Spring Security 核心解读(二)自定义认证授权体系

news2024/12/24 0:22:38

自定义认证授权体系

    • 概述
    • 自定义认证
      • 定义登录接口
      • 配置 Security 放行策略
      • 定义通用登录过滤器并将其配置到 Security 过滤器链上
      • 定义资源接口
      • 在 Security 授权设置中放行
      • 启动项目
    • 结尾

概述

以前使用Spring Security 时,基本都是按部就班参考文档开发。
基本是从 User,UserDetails,UserDetailsService以及参考 UsernamePasswordAuthenticationFilter 开始。
现在看来,这种方式略显僵化,不够灵活。

今天以一种全新的方式来实现自定义认证授权。
先说明一点,考虑到现在前端的多样性以及cookie使用的局限性等,现在采用header+token方式认证授权,摒弃cookie+session的方式

自定义认证

定义登录接口

    /**
     * 自定义登录接口,Security 对其放行
     * @return
     */
    @PostMapping("login")
    public String login(){
        log.info("login....");
        // TODO: 2023/6/3 验证登录参数,通过后直接下发token,这里的token可以是无状态jwt 也可以是存储在服务端的有状态token
        return "token";
    }

配置 Security 放行策略

明确不用的过滤器给禁了

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(httpRequest ->
                        httpRequest
                                .antMatchers("/login").permitAll()
                                .anyRequest().denyAll()
                )
                // 不走默认form表单以及默认登录页
                .formLogin().disable()
                // 禁用csrf,不走cookie相关认证
                .csrf().disable()
                // 禁用session,不用session,采用header认证
                .sessionManagement().disable()
    );
    return http.build();
}

定义通用登录过滤器并将其配置到 Security 过滤器链上

默认,Security使用的是 用户名密码显式 + cookie(session)隐式登录方式。
我们这里将其改造成 自定义显式登录 + header或者其他任意方式 隐式登录

/**
 * 通用登录过滤器
 * 替代传统 cookie -> session 的登录方式
 */
public class CustomAuthenticationFilter extends OncePerRequestFilter {

    private final Logger logger = LoggerFactory.getLogger(CustomAuthenticationFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
            // 这里支持 header 和 查询参数的方式传递token
        String token = request.getHeader("token");
        if (!StringUtils.hasText(token)) {
            token = request.getParameter("token");
        }
        if (!StringUtils.hasText(token)) {
            logger.info("请求头没有 token,跳过当前登录器");
            filterChain.doFilter(request, response);
            return;
        }
        logger.info("调用通用登录过滤器, token = {}", token);
        try {
            // 这里做简单校验,实际开发中,做正常校验,通过后,提取认证信息,进行认证
            if (Objects.equals(token, "token")) {
                UsernamePasswordAuthenticationToken authenticationToken
                        = UsernamePasswordAuthenticationToken.authenticated("zhangsan", "zs", Collections.emptyList());
                SecurityContext context = SecurityContextHolder.createEmptyContext();
                context.setAuthentication(authenticationToken);
                SecurityContextHolder.setContext(context);
            }
            filterChain.doFilter(request, response);
        } finally {
            SecurityContextHolder.clearContext();
        }
    }

    @Override
    protected boolean shouldNotFilterErrorDispatch() {
        return true;
    }
}

将通用登录过滤器配置到 SecurityFilterChain 上

httpRequest.addFilterBefore(new CustomAuthenticationFilter(), AnonymousAuthenticationFilter.class)

定义资源接口

分别定义公共接口,需登录的接口,需特定权限的接口

@RestController
@Slf4j
public class HellController {

    @GetMapping("common")
    public String common(){
        log.info("common....");
        return "common";
    }

    @GetMapping("auth")
    public String auth(){
        log.info("auth....");
        return "auth";
    }

    @GetMapping("admin")
    public String admin(){
        log.info("admin....");
        return "admin";
    }
}

在 Security 授权设置中放行

httpRequest
	.antMatchers("/common").permitAll()
	.antMatchers("/auth").authenticated()
	.antMatchers("/admin").hasAuthority("admin")
	.antMatchers("/login").permitAll()
	.anyRequest().denyAll()

启动项目

  • 首先访问公共接口,可以直接访问
    在这里插入图片描述
  • 然后访问需要认证的接口
    在这里插入图片描述
    可以看到这里的响应码为 403,表示无权访问。这里没有提示信息,是由于禁用了 默认的Form表单相关的配置,还没有配置异常处理器的缘故,这个后面再说。
    继续,这里模拟登录,拿到的token为"token",然后在参数或者header上面进行传递。
    在这里插入图片描述
    在这里插入图片描述
    可以看到这里成功访问 auth 接口
  • 然后我们去访问 需要admin权限的接口
    在这里插入图片描述
    我们可以看到,即使带了token,依然是403,因为当前这个用户没有admin权限。我们修改修改通用登录过滤器,再给一个带有admin权限的token进行测试。
if (Objects.equals(token, "token") || Objects.equals(token, "admin")) {
    UsernamePasswordAuthenticationToken authenticationToken
            = UsernamePasswordAuthenticationToken.authenticated("zhangsan", "zs"
            , Objects.equals(token, "admin") ? AuthorityUtils.createAuthorityList("admin") : Collections.emptyList());
    SecurityContext context = SecurityContextHolder.createEmptyContext();
    context.setAuthentication(authenticationToken);
    SecurityContextHolder.setContext(context);
}

调整部分,如果token是 admin ,那么就赋予 admin 权限,普通token依然只有 普通认证权限,再次启动项目。

我们将token 换成 admin
在这里插入图片描述
可以看到,成功获取到数据。

结尾

Security 里面东西其实很多,但是在日常开发中常用的就那些。最主要的是要理解其设计思想和基础架构,不太清楚的可以看看 上一篇文章

下一节,将学习 Security 下跨域及认证授权异常处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/606383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python开发】FastAPI 06:处理错误

某些情况下,有必要向客户端(包括前端浏览器、其他应用程序、物联网设备等)返回错误提示,以便客户端能够了解错误的类型,从而做出应对。 目录 1 默认处理 1.1 错误介绍 1.2 使用 HTTPException 2 自定义处理 2.1 自…

论旅行之收获2

论旅行之收获2 概况站点第一站:北京市大兴区大兴机场基本情况吐槽小小趣事 第二站:云南省昆明长水机场云南省昆明市五华区基本概况经济分析 第三站:昆明站大理站云南省大理白族自治州大理市下关基本情况 第四站:云南省大理白族自治…

操作系统-进程和线程-处理机调度

目录 一、调度的概念 1.1调度的层次 1.1.1高级调度(作业调度) 1.1.2中级调度(内存调度) 1.1.3低级调度(进程调度) 1.2状态模型 1.3调度的时机 1.4调度方式 1.5进程的切换与过程 二、调度算法的评价指标 2.1CPU利用率 2.2吞吐量 2.3周转时间 2.4带权周转时间 2.5等…

Ansible基础6——文件模块、jinja2模板

文章目录 一、常用文件模块1.1 blockinfile模块1.2 file模块1.2.1 创建文件并赋予权限1.2.2 创建目录并赋予权限1.2.3 创建软连接1.2.4 删除文件或目录 1.3 fetch模块1.4 lineinfile模块1.5 stat模块1.6 synchronize模块 二、jinja2模板2.1 构建jinja2模板2.2 管理jinja2模板2.…

LVGL学习(1):中文字体的转换和汉字显示

在使用LVGL的过程中,我们难免需要显示汉字,所以这篇文章就来介绍一下如何转换中文汉字并成功显示到LVGL中。 文章目录 1 字体转换1.1 GUI Guider自动转换1.2 在线转换 2 字体的使用 1 字体转换 1.1 GUI Guider自动转换 打开GUI Guide,创建…

SAP-MM-批次删除归档操作

对于物料主数据的批次管理,一旦一个物料设置了批次管理,并已经产生了业务数据,但是发现当初业务主数据搞错了,此物料不需要在SAP系统进行批次管理,是否就无法取消其批次管理了呢,因为如果要取消此批次管理&…

Java: 字符集详解

1.计算机的存储规则 在计算机中,任意数据都是以二进制的形式来存储的。 每一个二进制数表示的0,1被称为比特位,8个比特位组成一个字节。 字节:计算机最小的存储单元。 2.ASCII字符集 用于存储英文字符,查询制定AS…

阿里云服务器开通全部端口流程

阿里云服务器端口怎么全部打开?在安全组中开启端口号,在安全组中把端口范围设置为-1/-1,授权对象填0.0.0.0/0,即可开通全部端口号,阿腾云来详细说下阿里云服务器端口全部打开教程: 阿里云服务器端口全部开…

结题报告范文

结题报告范文篇一 项目名称:__________ 项目编号: 项目负责人:_________ 专业年级:__________ 所在学院:__________ 起止年月: 电 话:__________ E-mail: 填表时期: 福建…

Vue基础入门(下)

<script src"https://unpkg.com/vuenext"></script> mixin混入&#xff08;局部使用&#xff09; 定义mixin对象 <script>// mixin 混入const mymixin{data(){return {number:2,count:1}},created(){console.log(mymixin created);},methods:{…

【Unity3D】Bloom特效

1 Bloom 特效原理 Bloom 特效是指&#xff1a;将画面中较亮的区域向外扩散&#xff0c;造成一种朦脓的效果。实现 Bloom 特效&#xff0c;一般要经过 3 个阶段处理&#xff1a;亮区域检测、高斯模糊、Bloom 合成。 本文完整资源见→Unity3D Bloom 特效。 1&#xff09;亮区域检…

OS-内存管理1- 4种基本管理方式(连续分配,页式,段式,段页)。

一&#xff0c;内存管理四种方式。 二&#xff0c;连续分配管理方式。 连续分配方式&#xff1a;为用户分配连续的内存空间。 1.单一连续分配方式 2.固定分区分配方式 3.动态分区分配方式 4.三种连续分配方式的对比。 三&#xff0c;基于页式存储管理。 1.页式 为进一步提高…

嵌入式系统中I2C总线通信基本方法

将 I2C spec 文章总结为一篇&#xff0c;目录如下 I2C Introduction I2C Architecture I2C Transfer I2C Synchronization And Arbitration I2C Hs-mode1、I2C Introduction 1、I2C 历史 I2C&#xff1a;Inter-Integrated Circuit&#xff0c;集成电路总线。 I2C 是 Philips…

部分网络结构记录

CVPR 2022 | Mobile-Former来了&#xff01;微软提出&#xff1a;MobileNetTransformer轻量化并行网络 文章链接: CVPR 2022 | Mobile-Former来了&#xff01;微软提出&#xff1a;MobileNetTransformer轻量化并行网络 - 知乎 (zhihu.com) Mobile-Former架构图 Mobile-Form…

Mybatis学习笔记一

目录 一、Mybatis特性二、快速入门1.导入依赖2.mybatis-config.xml配置3.创建mapper接口4.创建MyBatis的映射文件5.通过junit测试功能 三、MyBatis获取参数值的两种方式&#xff08;重点&#xff09;1.单个字面量类型的参数2.多个字面量类型的参数3.map集合类型的参数4.实体类类…

【六一特别文章】Python编写一个六一儿童节问答小游戏及趣味比赛

随着六一儿童节的到来&#xff0c;我们可以为孩子们编写一个有趣的小游戏&#xff0c;让他们在游戏中学习有关六一儿童节的知识。本文将介绍如何用Python编写一个六一儿童节问答小游戏及趣味比赛。 首先&#xff0c;我们需要准备一些有关六一儿童节的问题和答案。这里我准备了…

云原生之docker详解

目录 1.云原生概念 1.1 云原生定义 1.2 云原生元素 1.2.1 微服务 1.2.2 DevOps 1.2.3 持续交付 1.2.4 容器化 2. Docker 2.1 Docker概述 2.1.1 Docker 定义 2.1.2 Docker应用场景 2.1.3 Docker的架构 2.2 Docker命令 2.2.1 docker进程相关命令 2.2.2 docker镜像…

htmlCSS-----CSS选择器(下)

目录 前言&#xff1a; 2.高级选择器 &#xff08;1&#xff09;子代选择器 &#xff08;2&#xff09;伪类选择器 &#xff08;3&#xff09;后代选择器 &#xff08;4&#xff09;兄弟选择器 相邻兄弟选择器 通用兄弟选择器 &#xff08;5&#xff09;并集选择器 &am…

测试进阶必备,这5款http接口自动化测试工具真的很香

现在市场上能做接口自动化测试的工具有很多&#xff0c;一搜一大把&#xff0c;让人眼花缭乱。我们去选择对应实现方式时&#xff0c;不管是框架体系还是成熟稳定的工具&#xff0c;核心目的都是期望引入的技术能在最低投入的情况下达到最优效果。 那么我们选择依据出来了&…

LearnOpenGL-高级OpenGL-9.几何着色器

本人初学者&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 文章目录 几何着色器使用几何着色器造几个房子爆破物体法向量可视化 几何着色器 简介 在顶点和片段着色器之间有一个可选的几何着色器几何着色器的输入是一个图元&#xff08;如点或三角形&#xff09;的一…