当前位置: 首页 > news >正文

认证授权概述和SpringSecurity安全框架快速入门

1. 认证授权的概述

1.1 什么是认证

进入移动互联网时代,大家每天都在刷手机,常用的软件有微信、支付宝、头条、抖音等

以微信为例说明认证的相关基本概念。在初次使用微信前需要注册成为微信用户,然后输入账号和密码即可登录微信,输入账户和密码登录微信的过程就是认证

系统为什么需要认证?

认证是为了保护系统的隐私数据和资源,用户的身份合法,方可访问该系统的资源

认证:用户认证就是判断一个用户的信息是否合法的过程,用户去访问系统资源时,系统需要要求验证用户的身份信息,身份合法方可继续访问,不合法则拒绝访问。常见的用户身份认证方式有:用户名和密码登录二维码登录手机短信登录指纹认证等方式

1.2 什么是会话

用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保证在会话中。会话就是系统为了保持当前用户的登录状态所提供的机制,常见的有基于session方式、基于token方式

1.2.1 基于session的认证

它的交互流程是:

用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中,发给客户端的session_id存放到cookie中。

这样用户客户端请求时带上session_id就可以验证服务器端是否存在session数据,以此完成用户的合法校验,当前用户退出系统或session过期销毁时,客户端的session_id也就无效了

在这里插入图片描述

1.2.2 基于Token的认证

它的交互流程是

用户认证成功后,服务端生成一个token(令牌)【唯一字符串】发给客户端,客户端可以放到cookie或sessionStorage等存储中,每次请求时带上token,服务端收到token通过验证后即可确认用户身份

基于session的认证方式由servlet规范定制,服务端要存储session信息,需要占用内存资源,客户端需要支持cookie;基于token的方式则一般不需要服务端存储token,并且不限制客户端的存储方式cookie sessionStorage LocalStorage Vuex。如今移动互联网时代更多类型的客户端[pC ,android,IOS,]需要接入系统,系统多是采用前后端分离的架构进行实现,所以基于token的方式更适合

使用前后端分离或后台使用了集群—一定采用token模式。

传统的项目前端和后端都在一个工程下—基于session模式。

1.3 什么是授权

还拿微信来举例子,微信登录成功后用户即可使用微信的功能,比如,发红包、发朋友圈、添加好友等,没有绑定银行卡的用户是无法发送红包的,绑定银行卡的用户才可以发红包,发红包功能、发朋友圈功能都是微信的资源即功能资源,用户拥有发红包功能的权限才可以正常使用发送红包功能,拥有发朋友圈功能的权限才可以便用发朋友圈功能,这个根据用户的权限来控制用户使用资源的过程就是授权。

  1. 权限【权限表】----资源【接口】

1.3.1 为什么要授权

认证是为了保证用户身份的合法性,授权则是为了更细粒度的对隐私数据进行划分,授权是在认证通过后发生的,控制不同的用户能够访问不同的资源。
授权:授权是用户认证通过根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则正常访问,没有权限则拒绝访问。

认证授权的框架: [1]shiro 轻量级的认证授权 它可以整合任意框架 它支持javase和javaee

​ [2]springsecurity 重量级的认证授权框架。它只能和spring整合,只支持javaee web框架。

spring非常麻烦,但是现在和springboot整合就很简单了。

2.概述springsecurity

官网:https://spring.io/projects/spring-security#overview

2.1 什么是spring security?

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Sprirg应用上下文中配置的Bean,充分利用了Spring IoC [],DI(控制反转Inversion of Control ,DI:Dependency Injection依赖主入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
以上解释来源于百度白科。可以一句话来概括,SpringSecurity 是一个安全框架。可以帮我们完成认证,密码加密,授权,,rememberme的功能【security:安全】

3.快速入门springsecurity

基于内存的数据。

引入依赖

 <!--引入springsecurity的依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>

创建接口资源——创建一个controller

@RestController
public class HelloController {@GetMapping("/hello")public String hello(){return "Hello~~~~~~~~~~~~~~~";}

启动项目并访问资源

在这里插入图片描述

发现:帮你跳转到登录页面。 因为springsecurity包含了很多过滤器,认证过滤器发现你没有登录就访问资源。默认调整到它内置的登录页面

在这里插入图片描述

账号为: user

密码: 在控制台可以看见

在这里插入图片描述

4. 自定义账号和密码

在配置文件中添加配置——但只能定义一个用户

#定义账号和密码 一旦自定义了账号和密码 原来自带的就不存在了 这里只能定义一个账号和密码
spring.security.user.name=admin
spring.security.user.password=123456

5. 定义多用户–基于内存

定义一个配置类——springboot版本2.7.0以下

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {//配置文件中的账号和密码失效@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.//基于内存完成认证和授权inMemoryAuthentication()// 表示用户名.withUser("lay")//表示密码.password("123456")//当前用户具有的角色.roles("admin")//表示具有的权限.authorities("user:select","user:delete","user:insert","user:update").and().withUser("xiumin").password("123456").roles("user").authorities("user:select","user:export");}

在这里插入图片描述

输入密码登录后报错

在这里插入图片描述

没有使用密码加密器。

解决:修改配置类——1.在配置类中添加密码加密器

    @Beanpublic PasswordEncoder passwordEncoder(){PasswordEncoder passwordEncoder=new BCryptPasswordEncoder();return passwordEncoder;}

修改配置类——给密码使用加密器

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("lay").password(passwordEncoder().encode("1007"))//添加密码加密器.roles("admin").authorities("user:select").and().withUser("lays").password(passwordEncoder().encode("10072")).roles("user").authorities("user:export");}

在password中添加密码加密器:passwordEncoder().encode("密码")

6. 密码加密器

分成两种类型: 对称加密和非对称加密

对称加密:表示加密和解密使用同一把密钥。

非对称加密: 表示加密和解密不是使用同一个密钥。 md5 hash

public class Test {public static void main(String[] args) {PasswordEncoder passwordEncoder=new BCryptPasswordEncoder();//用于加密String encode = passwordEncoder.encode("123456");String encode2 = passwordEncoder.encode("123456");String encode3 = passwordEncoder.encode("123456");System.out.println(encode);System.out.println(encode2);System.out.println(encode3);//安全.boolean matches = passwordEncoder.matches("123456", encode2);System.out.println("是否密码正确:"+matches);}

7. 获取当前用户的信息

// springsecurity默认把当前用户的信息保存SecurityContext上下文中.
@GetMapping("info")public Authentication info(){//获取SecurityContext对象SecurityContext context = SecurityContextHolder.getContext();//把用户得到信息封装到Authontication类中--用户名---角色以及权限---状态[]Authentication authentication = context.getAuthentication();UserDetails principal = (UserDetails) authentication.getPrincipal();// System.out.println(principal.getUsername());return authentication;}

springsecurity默认为当前用户的信息保存在SecurityContext上下文中

  1. 首先获取SecurityContext对象

    SecurityContext context = SecurityContextHolder.getContext();

    SecurityContextHolder:是安全上下文容器,可以在此得知操作的用户是谁,该用户是否已经被验证,它拥有哪些角色权限,这些都被保存在SecurityContextHolder中

  2. 返回认证信息——getAuthentication()方法

    Authentication authentication = context.getAuthentication();

  3. 返回身份信息——getPrincipal()方法。UserDetail便是Spring对身份信息封装的一个接口

    UserDetails principal = (UserDetails) authentication.getPrincipal();

  4. Authentication接口-认证信息包括:

    • getAuthorities():权限信息列表,默认是GrantedAuthority接口的一些实现类,通常是代表权限信息的一系列字符串
    • getCredentials():密码信息,用户输入的密码字符串,在认证过后通常会被移除,用于保障安全
    • getDetails():细节信息,web应用中的实现接口通常为WebAuthenticationDetails,它记录了访问者的ip地址和sessionId的值
    • getPrincipal():身份信息,大部分情况下返回的是UserDetails接口的实现类,也是框架中常用接口之一

8. security零散配置

    @Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin()//登录页面;.loginPage("/login.html")//登录的处理路径 默认 /login.loginProcessingUrl("/login").successForwardUrl("/success") //登录成功转发的路径 必须为post请求.failureForwardUrl("/fail") //登录失败转发的路径 必须为post请求.permitAll(); //上面的请求路径无需认证http.csrf().disable();//禁用跨域伪造请求的过滤器//除了上的请求,其他请求都需要认证http.authorizeRequests().anyRequest().authenticated();}
  1. 设置跳转到指定的登录页面——loginPage("/login.html")
  2. 设置登录的处理路径——loginProcessingUrl("/login")【默认登录的处理路径为:/login】
  3. 设置成功转发的路径——successForwardUrl("/success")必须为Post请求
  4. 设置登录失败转发的路径——failureForwardUrl("/fail")必须为Post请求
  5. 表名上面的请求路径无需认证——permitAll()
  6. 禁用跨域伪造请求的过滤器——http.csrf().disable();
  7. 设置处理以上的请求,其他请求都需要认证——http.authorizeRequests().anyRequest().authenticated();

9. security完成授权

授权:把当前用户具有的权限和对应的资源绑定的过程

授权一定发生在认证后

步骤

  • 定义一些资源接口
    @GetMapping("select")public String select(){System.out.println("查询用户");return "查询用户";}@GetMapping("insert")public String insert(){System.out.println("添加用户");return "添加用户";}@GetMapping("update")public String update(){System.out.println("修改用户");return "修改用户";}@GetMapping("delete")public String delete(){System.out.println("删除用户");return "删除用户";}@GetMapping("export")public String export(){System.out.println("导出用户");return "导出用户";}
  • 修改配置类

    在配置类中将资源和权限绑定

http.authorizeRequests().
//user/select资源与user:select权限绑定
antMatcher("/user/select").hasAuthority("user:select")
antMatcher("/user/insert").hasAuthority("user:insert")
antMatcher("/user/update").hasAuthority("user:update")
antMatcher("/user/delete").hasAuthority("user:delete")
antMatcher("/user/export").hasAuthority("user:export");

10. 使用注解完成授权

上述的授权代码比较麻烦,我们可以使用注解完成授权的过程

步骤

  • 开启security授权的注解驱动

    @EnableGlobalMethodSecurity(prePostEnabled = true)
    
  • 在资源上使用注解

    @PreAuthorize("hasAuthority(‘权限’)——资源执行前判断当前用户是否拥有该权限

     @GetMapping("select")@PreAuthorize("hasAuthority('user:select')") //资源执行前判断当前用户是否拥有user:select权限public String select(){System.out.println("查询用户");return "查询用户";}
    
  • 修改配置类*——将配置类中上述的手动绑定的代码删除

11. 处理权限不足

权限不足,使其跳转到指定页面

  • 首先创建一个用于当权限不足时要跳转的页面

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>Title</title>
    </head>
    <body>
    权限不足, 请联系管理员!!!!!!!!
    </body>
    </html>
    
  • 修改配置类

    http.exceptionHandling().accessDeniedPage("/页面名称");

    //指定权限不足跳转的页面http.exceptionHandling().accessDeniedPage("/403.html");
    

相关文章:

认证授权概述和SpringSecurity安全框架快速入门

1. 认证授权的概述 1.1 什么是认证 进入移动互联网时代&#xff0c;大家每天都在刷手机&#xff0c;常用的软件有微信、支付宝、头条、抖音等 以微信为例说明认证的相关基本概念。在初次使用微信前需要注册成为微信用户&#xff0c;然后输入账号和密码即可登录微信&#xff0c…...

docker常用命令集锦

目录 一、查看版本信息 1.1 查看 Docker CLI 版本&#xff1a; 1.2 查看 Docker 详细版本信息&#xff1a; 1.3 查看 Docker 系统信息&#xff1a; 二、进入和退出容器 2.1 进入容器&#xff1a; 2.2 退出容器&#xff1a; 2.3 查看容器日志&#xff1a; 2.4 查看容器的…...

学习Java的日子 Day56 数据库连接池,Druid连接池

Day56 1.数据库连接池 理解&#xff1a;池就是容器&#xff0c;容器中存放了多个连接对象 使用原因&#xff1a; 1.优化创建和销毁连接的时间&#xff08;在项目启动时创建连接池&#xff0c;项目销毁时关闭连接池&#xff09; 2.提高连接对象的复用率 3.有效控制项目中连接的…...

如何实现PostgreSQL对某一张表的WAL日志进行记录

PostgreSQL 没有内置的 binlog&#xff08;binary log&#xff09;机制像 MySQL 那样。它使用 Write-Ahead Logging (WAL) 来记录数据库的变更。要将这些变更记录到某张表中&#xff0c;通常可以使用逻辑复制&#xff08;Logical Replication&#xff09;和触发器&#xff08;T…...

机器学习数学基础(2)--最大似然函数

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 在机器学习和统计学领域中&#xff0c;似然函数&#xff08;Likelihood Function&#xff09;是一个至关重要的概念。…...

详解 @RequestHeader 注解在 Spring Boot 中的使用

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119@qq.com] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? 专栏导…...

C# 表达式树的简介与说明

文章目录 1. 表达式树是什么&#xff1f;2. 表达式树的基本组成3. 构建表达式树的步骤4. 表达式树的使用场景5. 示例代码6. 总结 在 C# 编程中&#xff0c;表达式树&#xff08;Expression Tree&#xff09;是一个强大的概念&#xff0c;它允许我们以代码的形式表示运行时的代码…...

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第六十三章 输入子系统实验

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...

[补题记录]Leetcode 15. 三数之和

传送门&#xff1a;三数之和 思路 为了去重&#xff0c;需要先排序。 排序之后&#xff0c;显然每一个 n u m s [ i ] nums[i] nums[i] 就可以作为三数之中的第一个数。 因此&#xff0c;对于每一个 i i i&#xff0c;第二、三个数只能在 [ i 1 , n ] [i 1, n] [i1,n]…...

什么是sql注入攻击,如何预防介绍一下mysql中的常见数据类型

什么是sql注入攻击&#xff0c;如何预防 sql注入攻击指的是应用程序对用户输入数据的合法性没有判断或者过滤不严格&#xff0c;在sql语句中插入任意的恶意语句进行非法操作。 预防方式1&#xff1a;使用预编译语句比如PrepareStatement&#xff0c;用户输入的所有数据都以参数…...

史上最全的Seata教学并且连接springcloudAlibaba进行使用

来都来了点个赞收藏一下在走呗~~&#x1f339;&#x1f339;玫瑰 一、Seata是什么 Seata&#xff08;Simple Extensible Autonomous Transaction Architecture&#xff0c;简单可扩展自治事务框架&#xff09;是一种分布式事务解决方案&#xff0c;旨在解决分布式系统中的事务…...

InternLM Git 基础知识

提交一份自我介绍。 创建并提交一个项目。...

【Unity模型】古代亚洲建筑

在Unity Asset Store上&#xff0c;一款名为"Ancient Asian Buildings Pack"&#xff08;古代亚洲建筑包&#xff09;的3D模型资源包&#xff0c;为广大开发者和设计师提供了一个将古代亚洲建筑风格融入Unity项目的机会。本文将详细介绍这款资源包的特点、使用方式以…...

木马后门实验

实验拓扑 实验步骤 防火墙 配置防火墙—充当边界NAT路由器 边界防火墙实现内部 DHCP 分配和边界NAT需求&#xff0c;其配置如下 登录网页 编辑接口 配置e0/0 配置e0/1 编辑策略 测试&#xff1a;内部主机能获得IP&#xff0c;且能与外部kali通信 kali 接下来开启 kali 虚…...

【React】useState:状态更新规则详解

文章目录 一、基本用法二、直接修改状态 vs 使用 setState 更新状态三、对象状态的更新四、深层次对象的更新五、函数式更新六、优化性能的建议 在 React 中&#xff0c;useState 是一个非常重要的 Hook&#xff0c;用于在函数组件中添加状态管理功能。正确理解和使用 useState…...

C#中的异步编程:Task、Await 和 Async

public async void DoSth() {await Task.Run(() > {//...DoSth...}); } ①函数的返回类型前加上&#xff1a; async ②函数内加上&#xff1a; await Task.Run(() > { }); ③在上面{ ... } 内添加要处理的程序代码&#xff0c; 这样运行到 DoSth() 函数就…...

SSRF-labs-master靶场

目录 file_get_content.php sql_connect.php download.php dns-spoofing.php dns_rebinding.php 访问链接 http://127.0.0.1/SSRF/# file_get_content.php 在编程语言中&#xff0c;有一些函数可以获取本地保存文件的内容。这些功能可能能够从远程URL以及本地文件 如果没…...

HBuilder X中配置vue-cli项目和UI库

目录 一.前端项目结构 二.在HBuilder X中搭建vue-cli项目 1. 安装node.js前端环境 2. HBuilder X创建一个vue-cli项目 3. vue-cli项目结构 4. 如何运行前端项目 5. 创建组件 6. 组件路由(页面跳转) 6.1 创建router目录 6.2 使用路由 6.3 在main.js中配置路由 6.4 路…...

如何用PostMan按照规律进行循环访问接口

①设置动态变量 步骤一: 设置环境变量 1. 创建环境变量集合 在 Postman 左上角选择 "环境"&#xff0c;然后点击 "添加" 来创建一个新的环境变量集合。给它起一个名称&#xff0c;比如 "uploadDemo". 2. 添加初始变量 在新创建的环境变量集…...

稳态准直太阳光模拟器仪器光伏电池组件IV测试

太阳能模拟器电池IV测试仪、单体测试仪&#xff0c;配备匹配标准的AAA Class稳态太阳能模拟器及相关测试附件&#xff0c;可对太阳能电池片的IV性能进行测量、分级分选等&#xff1b; 介绍 AAA class太阳光模拟器整合完整的IV测量系统&#xff0c;针对各种太阳能电池的性能&a…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...