阐述Spring Security概念及其运用于实战

Spring Security(安全校验)

1. 概述

Spring Security是Spring项目组提供的安全服务框架,核心功能包括认证授权.为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作.
在如今开发模式中,Spring Security已经成为Java程序员必备的一项技术,简化认证和授权开发的首选项,
其核心为认证和授权,我们先来了解一下何为认证和授权,理解其概念.

2. 认证

认证是指系统判断用户的身份是否合法,合法可继续访问,不合法则会拒绝访问.在生活中我们很常见认证的方式,例如人脸识别认证,指纹认证,用户名密码的登录,手机短信的登录等方式
认证的目的是保护系统的隐私数据和资源,用户的身份合法 才能访问资源.
注: SpringSecurity的依赖为(基于Spring Boot)

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.1 内存认证

内存认证的概念,及用户的数据存放在内存当中,数据在代码中写死,项目启动便加载到内存当中.代码如下

@Configuration
public class SpringSecurityConfig{@Beanpublic UserDetailsService userDetailsService(){//1.创建内存管理对象InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();//2.创建权限对象UserDetails user1 = User.withUsername("zhangsan").password("123").authorities("admin").build();UserDetails user2 = User.withUsername("lisi").password("123").authorities("admin").build();//3.封装到manager当中manager.createUser(user1);manager.createUser(user2);return manager;}
}

这种认证方式很明显,不灵活,代码写死,用户信息仅有代码所包含部分.这不符合我们的业务开发,应该连接于数据库.所以Spring Security提供了另一套配置.我们需要创建一个配置类去实现UsersDetailsService接口.(这里我使用的是Mybatis-Plus去操作数据库)
代码如下:

@Service
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate UsersMapper usersMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//1.查询数据库,是否存在对象Users users = usersMapper.selectOne(new QueryWrapper<Users>().lambda().eq(Users::getUsername, username));//2.判断用户是否为空if(users == null){//2.1.1 为空直接返回return null;}//3.封装成userDetails对象UserDetails userDetails = User.withUsername(users.getUsername()).password(users.getPassword()).authorities("admin").build();//5.返回return userDetails;}
}

2.2 密码编码

为了数据的安全性,通常我们存储到数据库的密码是经过转码的,即密文存储,所以我们需要配置转码的配置类,校验时才能检查对应的密码是否一致
Spring Security提供了BCryptPasswordEncoder编码配置类,我们注入一下即可.

/*** 密码解码配置* @return*/@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}

2.3 认证成功与失败的处理

当认证成功之后,我们可能要对用户做一些信息上的配置或者其他的调整,需要介入java代码,同理失败也得控制用户的信息,防止用户恶意破坏信息.
我们需要配置SecurityFilterChain,由名字也可知道这是经过SpringSecurity框架的执行链.我们可以在这配置我们的业务需求.代码如下(包含前端路径的可自行配置,这里我使用的是thymeleaf,在resource下创建templates目录,编写对应页面就可)
注: 别忘了配置第二步允许静态资源的访问

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {//1.配置登录表单httpSecurity.formLogin(form ->{form.loginPage("/login.html") //自定义登录页面.loginProcessingUrl("/login")   //登录路径,表单向该路径提交,提交后自动执行MyUserDetailService的方法.usernameParameter("username")  //表单中用户名项.passwordParameter("password")  //表单中的密码项.successHandler(new MyLoginSuccessHandler())    //登录成功跳转页面.failureHandler(new MyLoginFailHandler());   //登录失败跳转页面});//2.配置需要认证和不需要认证的资源httpSecurity.authorizeHttpRequests(resp->{resp.requestMatchers("/login.html","/fail.html").permitAll(); //不需要认证的资源resp.requestMatchers("/css/*.css","/js/*.js","/img/**").permitAll();    //静态资源resp.anyRequest().authenticated();  //其余所有请求都需要认证});//3.关闭csrf防护(若不关闭资源无法访问)httpSecurity.csrf(csrf->{csrf.disable();});
}

认证成功的处理器

public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {//拿到登录用户的信息UserDetails userDetails = (UserDetails) authentication.getPrincipal();System.out.println("用户名:"+userDetails.getUsername());System.out.println("登录之后的其余操作");//重定向到主页response.sendRedirect("/main");}
}

认证失败的处理器

public class MyLoginFailHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {System.err.println(exception.getMessage());System.out.println("登录失败");response.sendRedirect("/fail.html");}
}

2.4 退出登录

用户需要退出登录时,我们需要清除他的会话信息及授权信息.配置如下(依旧配置在上述配置类SpringSecurityConfig的方法当中)

//配置退出登录功能httpSecurity.logout(out->{
//                out.logoutUrl("/logout")out.logoutSuccessHandler(new MyLoginLogOutSuccessHandler()).invalidateHttpSession(true)    //清除session记录,默认为true.clearAuthentication(true);    //清除授权记录,默认为true});

2.5 记住我

在许多登录场景当中,往往会有记住我这个选项.可以在一段时间内记住用户的登录信息,用户下次访问时便可以不再需要登录.我们可以思考一下怎么去做到这个事情.大家应该都接触过JWT令牌,对token字段我们并不陌生.我们可以在用户使用记住我这个功能时,生成一个Token令牌,保存到数据库当中,下次用户再来访问我们去数据库查询是否有这样一个Token即可.
SpringSecurity帮我们实现了这样一个功能,需要我们配置一下即可.其功能演示大概为:

首先我们得有这样一个存放token的表,利用SpringSecurity配置生成表(别忘了在配置文件中配置DataSource哦)

@Configuration
public class RememberMeConfig {@Autowiredprivate DataSource dataSource;//生成令牌@Beanpublic PersistentTokenRepository getPersistentTokenRepository(){// 为Spring Security 自带的令牌控制器设置数据源JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();jdbcTokenRepository.setDataSource(dataSource);// 开启自动建表,第一次启动时需要,第二次就注释掉
//        jdbcTokenRepository.setCreateTableOnStartup(true);//返回return jdbcTokenRepository;}
}

注: 第一次启动运行时可以直接这样写,第二次启动记得把jdbcTokenRepository.setCreateTableOnStartup(true);给注释掉,若忘记啦也没有关系,控制台会报错(表已经存在),根据原因我们再来处理也可

再回到SpringSecurityConfig当中,将这个配置类生效

//注入这两个类@Autowiredprivate PersistentTokenRepository persistentTokenRepository;@Autowiredprivate MyUserDetailService myUserDetailService;
//配置记住我httpSecurity.rememberMe(remember->{remember.tokenRepository(persistentTokenRepository) //配置持久化token仓库.userDetailsService(myUserDetailService)	//配置权限处理对象,即认证逻辑对象.tokenValiditySeconds(30); //配置token的保持时间,即多久以后失效});

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

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

相关文章

5 DSL入门_02精确查询

1. 精确查询 (1)一般是查找keyword,数值&#xff0c;日期&#xff0c;boolean等类型字段&#xff0c;所以不会对搜索条件分词&#xff0c;常见的有&#xff1a;term,range//只查询city南京市鼓楼区,且不会对搜索词分词 get /hotel/_search {"query":{"term&quo…

RabbitMQ实战宝典:从新手到专家的全面探索

前言 在当今分布式系统架构中&#xff0c;消息队列已成为不可或缺的一部分&#xff0c;而RabbitMQ作为其中的佼佼者&#xff0c;凭借其强大的功能和灵活性&#xff0c;广泛应用于各种规模的应用场景中。本文将带你从基础概念出发&#xff0c;深入探讨RabbitMQ的核心特性&#…

计算机网络 静态路由及动态路由RIP

一、理论知识 1.静态路由 静态路由是由网络管理员手动配置在路由器上的固定路由路径。其优点是简单和对网络拓扑变化不敏感&#xff0c;缺点是维护复杂、易出错&#xff0c;且无法自动适应网络变化。 2.动态路由协议RIP RIP是一种基于距离向量的动态路由协议。它使用跳数作…

springboot+vue+mysql+mybatis 二手交易平台

springbootvuemysqlmybatis 二手交易平台 相关技术 javaspringbootmybatismysqlvueelementui

芯片后端之 PT 使用 report_timing 产生报告如何阅读

今天,就PT常用的命令,做一个介绍,希望对大家以后的工作,起到帮助作用。 在PrimeTime中,使用report_timing -delay max命令生成此报告。switch -delay max表示定时报告用于设置(这是默认值)。 首先,我们整体看一下通过report_timing 运行之后,报告产生的整体样式。 pt…

Bootstrap 5 导航

Bootstrap 5 导航 Bootstrap 5 是一个流行的前端框架&#xff0c;用于快速开发响应式和移动设备优先的网站。在本文中&#xff0c;我们将深入探讨 Bootstrap 5 中的导航组件&#xff0c;包括其功能、自定义选项以及如何在实际项目中有效使用它们。 简介 Bootstrap 5 的导航组…

vscode用vue框架2,续写登陆页面逻辑,以及首页框架的搭建

目录 前言&#xff1a; 一、实现登录页信息验证逻辑 1.实现登录数据双向绑定 2.验证用户输入数据是否和默认数据相同 补充知识1&#xff1a; 知识点补充2&#xff1a; 二、首页和登录页之间的逻辑(1) 1. 修改路由&#xff0c;使得程序被访问先访问首页 知识点补充3&am…

numpy.ndarray数据计算及操作集锦

目录 1. numpy.ndarray各列求均值1.1 列1.2 行 1. numpy.ndarray各列求均值 1.1 列 要对 v_sec_trans 数组的每一列求均值&#xff0c;可以使用 numpy 库中的 mean 函数。以下是具体的代码示例&#xff1a; import numpy as np# 定义 v_sec_trans 数组 v_sec_trans np.array…

Qt 实战(5)布局管理器 | 5.1、DPI对布局的影响

文章目录 一、DPI对布局的影响1、什么是DPI&#xff1f;2、DPI对布局的影响3、优化布局以适应不同DPI4、总结 前言&#xff1a; 在开发跨平台桌面应用程序时&#xff0c;DPI&#xff08;Dots Per Inch&#xff0c;每英寸点数&#xff09;是一个不可忽视的因素。DPI决定了屏幕上…

【STM32】STM32通过I2C实现温湿度采集与显示

目录 一、I2C总线通信协议 1.I2C通信特征 2.I2C总线协议 3.软件I2C和硬件I2C 二、stm32通过I2C实现温湿度&#xff08;AHT20&#xff09;采集 1.stm32cube配置 RCC配置&#xff1a; SYS配置&#xff1a; I2C1配置&#xff1a; USART1配置&#xff1a; GPIO配置&#…

二叉树经典OJ练习

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 二叉树经典OJ练习 收录于专栏【数据结构初阶】 本专栏旨在分享学习数据结构学习的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 前置说…

python:psutil获取指定进程Cpu及Memory使用的GUI界面

1导入依赖库 import os import psutil import time from pyecharts import options as opts from pyecharts.charts import Line import PySimpleGUI as sg from datetime import datetime from concurrent.futures import ThreadPoolExecutor import ctypes import sys2主界面…

八、(正点原子)Linux内核定时器实验

定时器是我们最常用到的功能&#xff0c;一般用来完成定时功能&#xff0c;本章我们就来学习一下 Linux 内核提供的定时器 API 函数&#xff0c;通过这些定时器 API 函数我们可以完成很多要求定时的应用。 Linux内核也提供了短延时函数&#xff0c;比如微秒、纳秒、毫秒延时函数…

YOLO系列--Anchor Based Anchor Free

一、Anchor based 1.1 Anchor的定义 Anchor也被称为锚框&#xff0c;预先设置目标的大概位置&#xff0c;然后再在这些预设框的基础上进行精细化的调整。调整过程被包括分类 判断预设框是属于正样本 or 负样本-和回归调整预测框的位置。 1.2 Anchor的产生 Anchor box是指在…

长尾分布(Long-tailed Distribution)

长尾分布&#xff08; L o n g − t a i l e d D i s t r i b u t i o n Long-tailed\ Distribution Long−tailed Distribution&#xff09;是统计学和概率论中的一个重要概念&#xff0c;用于描述一组数据中尾部&#xff08;即远离均值的部分&#xff09;包含了相对较多极端值…

【Linux基础】SSH登录

SSH简介 安全外壳协议&#xff08;Secure Shell Protocol&#xff0c;简称SSH&#xff09;是一种加密的网络传输协议&#xff0c;可在不安全的网络中为网络服务提供安全的传输环境。 SSH通过在网络中建立安全隧道来实现SSH客户端与服务器之间的连接。 SSH最常见的用途是远程登…

LeetCode 算法:二叉树的最大深度 c++

原题链接&#x1f517;&#xff1a;二叉树的最大深度 难度&#xff1a;简单⭐️ 题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,…

【高考选专业 | 家长篇】2024,计算机何去何从?小P老师带你看

目录 2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f;1.行业竞争现状2.专业前景分析 2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f; 随着2024年高考落幕&#xff0c;数百万高三学生又将面临人生中的重要抉择&#xff1a;选择大学专业。有人欢喜&#x…

如何在Java中实现高效的缓存机制

如何在Java中实现高效的缓存机制 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 引言 在大多数软件系统中&#xff0c;缓存机制是提高性能和响应速度的关键技…

操作系统真象还原:用户进程

第11章-用户进程 这是一个网站有所有小节的代码实现&#xff0c;同时也包含了Bochs等文件 11.1 为什么要有任务状态TSS Linux 任务切换未采用 Intel 的做法&#xff0c;而是用了一套自己的方法&#xff0c;只是用了 TSS 的一小部分功能。 操作系统最直接控制的就是 CPU&…