Spring Security 入门1

news2024/11/26 9:51:06

1. 概述

基本上,在所有的开发的系统中,都必须做认证(authentication)和授权(authorization),以保证系统的安全性。

authentication [ɔ,θɛntɪ’keʃən] 认证
authorization [,ɔθərɪ’zeʃən] 授权

以论坛举例子:

【认证】你要登录论坛,输入用户名张三,密码 1234,密码正确,证明你张三确实是张三,这就是 authentication。
【授权】再一 check 用户张三是个版主,所以有权限加精删别人帖,这就是 authorization 。

认证解决“你是谁”的问题,授权解决“你能做什么”的问题。

2. 快速入门

2.1 引入依赖

在 pom.xml 文件中,引入相关依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-01-springsecurity-demo</artifactId>

    <dependencies>
        <!-- 实现对 Spring MVC 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 实现对 Spring Security 的自动化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>

</project>

2.2 配置文件

在 application.yml 中,添加 Spring Security 配置,如下:

spring:
  # Spring Security 配置项,对应 SecurityProperties 配置类
  security:
    # 配置默认的 InMemoryUserDetailsManager 的用户账号与密码。
    user:
      name: user # 账号
      password: user # 密码
      roles: ADMIN # 拥有角色

在 spring.security 配置项,设置 Spring Security 的配置,对应 SecurityProperties 配置类。
默认情况下,Spring Boot UserDetailsServiceAutoConfiguration 自动化配置类,会创建一个内存级别的 InMemoryUserDetailsManager Bean 对象,提供认证的用户信息。

  • 这里,我们添加了 spring.security.user 配置项,UserDetailsServiceAutoConfiguration 会基于配置的信息创建一个用户 User 在内存中。
  • 如果,我们未添加 spring.security.user 配置项,UserDetailsServiceAutoConfiguration 会自动创建一个用户名为 “user” ,密码为 UUID 随机的用户 User 在内存中。

2.3 AdminController

创建 AdminController 类,提供管理员 API 接口。代码如下:

// AdminController.java

@RestController
@RequestMapping("/admin")
public class AdminController {

    @GetMapping("/demo")
    public String demo() {
        return "示例返回";
    }

}
  • 这里,我们先提供一个 “/admin/demo” 接口,用于测试未登录时,会被拦截到登录界面。

2.4 简单测试

执行 Application#main(String[] args) 方法,运行项目。

项目启动成功后,浏览器访问 http://127.0.0.1:8080/admin/demo 接口。因为未登录,所以被 Spring Security 拦截到登录界面。如下图所示:
在这里插入图片描述
因为我们没有自定义登录界面,所以默认会使用 DefaultLoginPageGeneratingFilter 类,生成上述界面。

输入我们在 「2.2 配置文件 」中配置的「user/user」账号,进行登录。登录完成后,因为 Spring Security 会记录被拦截的访问地址,所以浏览器自动动跳转 http://127.0.0.1:8080/admin/demo 接口。访问结果如下图所示:

3. 进阶使用

在示例一中,我们会看看如何自定义 Spring Security 的配置,实现权限控制。

3.1 SecurityConfig

在 cn.iocoder.springboot.lab01.springsecurity.config 包下,创建 SecurityConfig 配置类,继承 WebSecurityConfigurerAdapter 抽象类,实现 Spring Security 在 Web 场景下的自定义配置。代码如下:

// SecurityConfig.java

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // ...

}

我们可以通过重写 WebSecurityConfigurerAdapter 的方法,实现自定义的 Spring Security 的配置。
首先,我们重写 #configure(AuthenticationManagerBuilder auth) 方法,实现 AuthenticationManager 认证管理器。代码如下:

// SecurityConfig.java

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.
            // <X> 使用内存中的 InMemoryUserDetailsManager
            inMemoryAuthentication()
            // <Y> 不使用 PasswordEncoder 密码编码器
            .passwordEncoder(NoOpPasswordEncoder.getInstance())
            // <Z> 配置 admin 用户
            .withUser("admin").password("admin").roles("ADMIN")
            // <Z> 配置 normal 用户
            .and().withUser("normal").password("normal").roles("NORMAL");
}

<X> 处,调用 AuthenticationManagerBuilder#inMemoryAuthentication() 方法,使用内存级别的 InMemoryUserDetailsManager Bean 对象,提供认证的用户信息。

  • Spring 内置了两种 UserDetailsManager 实现:
    • InMemoryUserDetailsManager,和「2. 快速入门」是一样的。
    • JdbcUserDetailsManager ,基于 JDBC的 JdbcUserDetailsManager 。
  • 实际项目中,我们更多采用调用 AuthenticationManagerBuilder#userDetailsService(userDetailsService) 方法,使用自定义实现的 UserDetailsService 实现类,更加灵活且自由的实现认证的用户信息的读取。

<Y> 处,调用 AbstractDaoAuthenticationConfigurer#passwordEncoder(passwordEncoder) 方法,设置 PasswordEncoder 密码编码器。

  • 在这里,为了方便,我们使用 NoOpPasswordEncoder 。实际上,等于不使用 PasswordEncoder ,不配置的话会报错。
  • 生产环境下,推荐使用 BCryptPasswordEncoder 。

<Z> 处,配置了「admin/admin」和「normal/normal」两个用户,分别对应 ADMIN 和 NORMAL 角色。相比「2. 快速入门」来说,可以配置更多的用户。

然后,我们重写 #configure(HttpSecurity http) 方法,主要配置 URL 的权限控制。代码如下:

// SecurityConfig.java

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            // <X> 配置请求地址的权限
            .authorizeRequests()
                .antMatchers("/test/echo").permitAll() // 所有用户可访问
                .antMatchers("/test/admin").hasRole("ADMIN") // 需要 ADMIN 角色
                .antMatchers("/test/normal").access("hasRole('ROLE_NORMAL')") // 需要 NORMAL 角色。
                // 任何请求,访问的用户都需要经过认证
                .anyRequest().authenticated()
            .and()
            // <Y> 设置 Form 表单登录
            .formLogin()
//                    .loginPage("/login") // 登录 URL 地址
                .permitAll() // 所有用户可访问
            .and()
            // 配置退出相关
            .logout()
//                    .logoutUrl("/logout") // 退出 URL 地址
                .permitAll(); // 所有用户可访问
}
  • <X> 处,调用 HttpSecurity#authorizeRequests() 方法,开始配置 URL 的权限控制。下面,是配置权限控制会使用到的方法:

    • #(String… antPatterns) 方法,配置匹配的 URL 地址,基于 Ant 风格路径表达式 ,可传入多个。
    • 【常用】#permitAll() 方法,所有用户可访问。
    • 【常用】#denyAll() 方法,所有用户不可访问。
    • 【常用】#authenticated() 方法,登录用户可访问。
    • #anonymous() 方法,无需登录,即匿名用户可访问。
    • #rememberMe() 方法,通过 remember me 登录的用户可访问。
    • #fullyAuthenticated() 方法,非 remember me 登录的用户可访问。
    • #hasIpAddress(String ipaddressExpression) 方法,来自指定 IP 表达式的用户可访问。
    • 【常用】#hasRole(String role) 方法, 拥有指定角色的用户可访问。
    • 【常用】#hasAnyRole(String… roles) 方法,拥有指定任一角色的用户可访问。
    • 【常用】#hasAuthority(String authority) 方法,拥有指定权限(authority)的用户可访问。
    • 【常用】#hasAuthority(String… authorities) 方法,拥有指定任一权限(authority)的用户可访问。
    • 【最牛】#access(String attribute) 方法,当 Spring EL 表达式的执行结果为 true 时,可以访问。

<Y> 处,调用 HttpSecurity#formLogin() 方法,设置 Form 表单登录。

如果想要自定义登录页面,可以通过 #loginPage(String loginPage) 方法,来进行设置。不过这里我们希望像「2. 快速入门」一样,使用默认的登录界面,所以不进行设置。
<Z> 处,调用 HttpSecurity#logout() 方法,配置退出相关。

如果想要自定义退出页面,可以通过 #logoutUrl(String logoutUrl) 方法,来进行设置。不过这里我们希望像「2. 快速入门」一样,使用默认的退出界面,所以不进行设置。

3.2 TestController

// TestController.java

@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/echo")
    public String demo() {
        return "示例返回";
    }

    @GetMapping("/home")
    public String home() {
        return "我是首页";
    }

    @GetMapping("/admin")
    public String admin() {
        return "我是管理员";
    }

    @GetMapping("/normal")
    public String normal() {
        return "我是普通用户";
    }

}
  • 对于 /test/echo 接口,直接访问,无需登录。
  • 对于 /test/home 接口,无法直接访问,需要进行登录。
  • 对于 /test/admin 接口,需要登录「admin/admin」用户,因为需要 ADMIN 角色。
  • 对于 /test/normal 接口,需要登录「normal/normal」用户,因为需要 NORMAL 角色。

可以按照如上的说明,进行各种测试。例如说,登录「normal/normal」用户后,去访问 /test/admin 接口,会返回 403 界面,无权限~

3.3 示例二

在示例二中,我们会看看如何使用 Spring Security 的注解,实现权限控制。

3.3.1 SecurityConfig

修改 SecurityConfig 配置类,增加 @EnableGlobalMethodSecurity 注解,开启对 Spring Security 注解的方法,进行权限验证。代码如下:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter

3.3.2 DemoController
创建 DemoController 类,提供测试 API 接口。代码如下:

// DemoController.java

@RestController
@RequestMapping("/demo")
public class DemoController {

    @PermitAll
    @GetMapping("/echo")
    public String demo() {
        return "示例返回";
    }

    @GetMapping("/home")
    public String home() {
        return "我是首页";
    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @GetMapping("/admin")
    public String admin() {
        return "我是管理员";
    }

    @PreAuthorize("hasRole('ROLE_NORMAL')")
    @GetMapping("/normal")
    public String normal() {
        return "我是普通用户";
    }

}

每个 URL 的权限验证,和「3.2 TestController」是一一对应的。

  • @PermitAll 注解,等价于 #permitAll() 方法,所有用户可访问。

重要!!!因为在「3.2.1 SecurityConfig」中,配置了 .anyRequest().authenticated()
,任何请求,访问的用户都需要经过认证。所以这里 @PermitAll 注解实际是不生效的。

也就是说,Java Config 配置的权限,和注解配置的权限,两者是叠加的。

  • @PreAuthorize 注解,等价于 #access(String attribute) 方法,,当 Spring EL 表达式的执行结果为 true 时,可以访问。

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

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

相关文章

Context capture/Pix4Dmapper/AutoCAD/CASS/EPS软件的安装流程与使用方法;土方量计算;无人机摄影测量数据处理

目录 专题一 无人机摄影测量技术应用现状及其发展 专题二 基本原理和关键技术讲解 专题三 无人机影像外业数据获取 专题四 数据处理环境建立与软件熟悉 专题五 GNSS数据土方量计算 专题六 基于无人机影像数据的正射影像制作 专题七 基于无人机影像数据的三维模型制作 专…

号称能打败MLP的KAN到底行不行?数学核心原理全面解析

前几天火爆的Kolmogorov-Arnold Networks是具有开创性&#xff0c;目前整个人工智能社区都只关注一件事LLM。我们很少看到有挑战人工智能基本原理的论文了&#xff0c;但这篇论文给了我们新的方向。 mlp或多层感知位于AI架构的最底部&#xff0c;几乎是每个深度学习架构的一部…

为什么 ChatGPT 不火了?

不火了是有原因的&#xff0c;下面我来从大部分人拿到 ChatGPT 之后的两大痛点开始讲起&#xff1a; 很多朋友拿到 ChatGPT 后的第一个痛点就是&#xff1a;用的不好 你经常会感觉到 ChatGPT 回答的好空&#xff0c;没有太多参考价值。 而第二个痛点则是&#xff1a;无处去用…

【Gateway】网关集成Knife4j—swagger接口文档

文章目录 前言一、相关配置1.网关gateway配置①.网关增加配置 pom文件②.网关增加配置 SwaggerHandler③.网关增加配置 SwaggerResourceConfig④.网关增加配置 SwaggerConfig 2.网关过滤器 二、接口文档使用1.访问文档2.查看文档 总结 前言 在日常开发中是需要前后端联调的&am…

加密杂谈:Base 向上,BSC 向下

Aerdrome 价格走过一轮&#xff0c;Base 一己之力扶持起巅峰 1B Mcap, 2B FDV 的百倍币&#xff0c;秀出了肌肉&#xff0c;其所带来的正外部性也进一步盘活了 Base 生态 反观 BSC 本轮哪怕靴子落地依然没个响&#xff0c;差距在哪里&#xff1f;本 Thread 将以此为切入点探讨…

Vue3:menu导航栏出现多个同一跳转路径的菜单处理

文章目录 需求整理实现思路实现过程 需求整理&#xff0c;实现思路 最近公司想将之前老的项目整理出来&#xff0c;因为这个老项目内容太杂什么页面都往里面塞&#xff0c;导致菜单特别多&#xff0c;公司就像将这个老的项目迁出来&#xff0c;这个旧的项目本来是后端PHP写的。…

【保姆级详细步骤教学用DOSBoxV0.74写出一个汇编语言程序输出Hello World!】

使用任何文本编辑器创建一个名为 HELLO.ASM 的文件&#xff0c;并将以下代码粘贴到文件中&#xff1a; .MODEL SMALL .STACK 100H.DATAMSG DB Hello, World!, $PROMPT DB 13, 10, Press any key to exit..., $.CODEMAIN PROCMOV AX, DATAMOV DS, AXMOV AH, 09HLEA DX, MSGINT …

用户页面触发点击事件和 js 执行点击事件的区别

文章目录 情景展示情况一&#xff1a;用户点击页面触发情况二&#xff1a;通过 js 触发点击 结果分析情况一情况二 其实这个谜底揭开之后&#xff0c;第一反应都是&#xff0c;哦~&#xff0c;非常简单&#xff0c;但是细节决定成败&#xff0c;我被这个细节毁掉了&#xff0c;…

docker资源限额

多数的应⽤场景要对Docker容器的运⾏内存进⾏限制&#xff0c;防⽌其使⽤过多的内存。 格式&#xff1a;-m或--memory 正常的内存大小 [rootadmin ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS …

硬件设计——滤波器设计_MIC用有源带通滤波器

“在已有的成熟稳定的滤波器基础上&#xff0c;根据业务需要对原设计进行优化调整以得到新的滤波器” 是滤波器设计的一种常用方法。 MIC用有源带通滤波器 介绍一种简单直观的带通滤波器以及计算过程&#xff0c;以作未来可参考的基线设计。该滤波器可用于音频信号&#xff0…

【算法】基础算法004之前缀和

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 本篇文章为大家带来前缀和…

【EI会议|投稿优惠】2024年物理化学与应用数学国际会议(IACPCAM 2024)

2024 International Conference on Physical Chemistry and Applied Mathematics 一、大会信息 会议名称&#xff1a;2024年物理化学与应用数学国际会议会议简称&#xff1a;IACPCAM 2024收录检索&#xff1a;提交Ei Compendex,CPCI,CNKI,Google Scholar等会议官网&#xff1a;…

基于树莓派的六足机器人方案设计+源代码+工程内容说明

文章目录 源代码下载地址项目介绍项目内容说明简单预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 项目内容说明 hardware为项目相关硬件设计 机械结构为六足机器人的3d建模工程&#xff0c;包括本体和云台遥控器在ESP32最小开发板上集成了MPU605…

Python面向对象编程思想的深入学习

魔术方法的使用 案例体验 class Student:def __init__(self, name, age):self.name nameself.age age# __str__魔术方法, 如果不去写这个方法&#xff0c;那么print输出的则是信息存储的内存地址。def __str__(self):return fStudent类对象&#xff0c;name:{self.name}, ag…

入门视频剪辑:视频合并不再难,批量嵌套合并的简单步骤

在数字媒体时代&#xff0c;视频剪辑已成为一项基本技能。无论是制作家庭电影、公司宣传片还是在线教育内容&#xff0c;视频剪辑都扮演着重要角色。对于初学者来说&#xff0c;视频剪辑可能看起来有些复杂&#xff0c;但掌握了正确的步骤和技巧后&#xff0c;你会发现它其实并…

【资源分享】PyCharm2020安装教程

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

了解外汇震荡类货币对特征与交易策略

外汇市场是全球最大的金融市场&#xff0c;每天的交易量超过6万亿美元。在这个市场上&#xff0c;货币对之间的价格变动反映了全球经济和政治动态。外汇货币对通常被分为三类&#xff1a;主要货币对、次要货币对和外来货币对。而在交易这些货币对时&#xff0c;市场表现通常分为…

MATLAB实现遗传算法优化同时取送货的车辆路径问题VRPSDP

同时取送货的车辆路径问题VRPSDP的数学模型如下: 模型假设 所有车辆的载重、容量等性能相同。每个客户的需求&#xff08;送货和取货量&#xff09;是已知的&#xff0c;且在服务过程中不会改变。车辆的行驶速度恒定&#xff0c;不考虑交通拥堵等实时路况变化。每个客户点只能…

记录一个RSA加密js逆向

network调试就不说了吧 pwd加密参数 搜索pwd参数定位逆向 可以看到有很多关键词 但是我们细心的朋友会发现加密函数关键字 encrypte 打上断点 调试 发现在断点处停止了 并且框选函数发现了一串加密值 虽然不一样但是大概率是这个 并且没你每次放置移开都会刷新 所以如果这个就是…

IP地址定位技术在网络安全中的作用

在当今数字化时代&#xff0c;网络安全已经成为企业、政府和个人面临的重要挑战之一。随着互联网的普及和网络攻击的增加&#xff0c;保护个人隐私和防止网络犯罪变得尤为重要。在这一背景下&#xff0c;IP地址定位技术作为网络安全的重要组成部分之一&#xff0c;发挥着关键作…