Spring Security 简单token配置
Spring Security 简单token配置
说明:非表单配置
先上码: https://gitee.com/qkzztx_admin/security-demo/tree/master/demo-two
环境:win10 idea2023 springboot2.7.6 maven3.8.6
代码清单说明
依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
Spring Security配置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;import javax.annotation.Resource;@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {@Resourceprivate MyAccessDeniedHandler myAccessDeniedHandler;@Resourceprivate MyAuthenticationEntryPoint myAuthenticationEntryPoint;@Resourceprivate AuthFilter authFilter;/*** security配置*/@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.csrf().disable() // 禁用csrf.authorizeRequests().antMatchers("/login").permitAll() // 允许任何人访问登录接口.and().sessionManagement(sessionManager -> sessionManager.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 不再管理session.authorizeRequests().anyRequest().authenticated() // 除了所有允许匿名访问的接口外,任何其他接口都得先认证.and().exceptionHandling(handling -> {handling.accessDeniedHandler(myAccessDeniedHandler) // 访问被拒绝的处理器.authenticationEntryPoint(myAuthenticationEntryPoint); // 认证失败的处理入口});// 设置用户访问前filterhttp.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class);return http.build();}/*** 用户数据*/@Beanpublic InMemoryUserDetailsManager userDetailsService() {UserDetails user = User.builder().username("user").password(passwordEncoder().encode("password")).roles("USER").build();return new InMemoryUserDetailsManager(user);}/*** 密码加密类*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}
放开/login的访问,方便用户认证,也就是抛弃了spring security的默认认证接口。
配置中,还有简单的用户查询服务,和一个默认的密码加密Bean。
import com.example.demo.two.controller.vo.R;
import com.example.demo.two.controller.vo.UserRequest;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;@RestController
public class LoginController {/*** 简单的存放用户登录认证成功信息的地方*/public final static Map<String, UserDetails> TOKEN_USERNAME = new HashMap<>();/*** SecurityConfig中配置的userDetailsService*/@Resourceprivate UserDetailsService userDetailsService;/*** SecurityConfig中配置的密码加密*/@Resourceprivate PasswordEncoder passwordEncoder;/*** 登录认证,获得token* @param userRequest 用户名和密码* @return 认证token*/@PostMapping("/login")public R login(@RequestBody UserRequest userRequest) {UserDetails userDetails = userDetailsService.loadUserByUsername(userRequest.getUsername());if (Objects.isNull(userDetails)) {return R.fail("用户名不存在");}if(passwordEncoder.matches(userRequest.getPassword(), userDetails.getPassword())) {// 认证成功发个tokenString token = UUID.randomUUID().toString();// 认证成功信息,简单存储TOKEN_USERNAME.put(token, userDetails);return R.success("登录成功", token);}return R.fail("密码不正确");}@GetMapping("/")public String index() {return "首页";}
}
简单的认证接口,注入了用户查询服务和密码加密Bean。
查询用户,判断密码,生成token,保存token,返回token,很简单。
还有一个首页接口是需要认证才能访问。
访问资源无权限时的处理类
import com.example.demo.two.controller.vo.R;
import com.example.demo.two.util.SimpleResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Slf4j
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {@Resourceprivate SimpleResponseUtil simpleResponseUtil;@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {// 无权限,一般返回403log.info("拒绝访问:{}", accessDeniedException.getMessage());simpleResponseUtil.write(response, R.fail("拒绝访问"));}
}
未登录访问资源时的处理类
import com.example.demo.two.controller.vo.R;
import com.example.demo.two.util.SimpleResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Slf4j
@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {@Resourceprivate SimpleResponseUtil simpleResponseUtil;@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {// 未认证,一般返回401log.info("未认证: {}", authException.getMessage());simpleResponseUtil.write(response, R.fail("未认证,请先认证"));}
}
自定义过滤器,以便识别用户身份,把用户身份设置到线程上下文中
import com.example.demo.two.controller.LoginController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;@Slf4j
@Component
public class AuthFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 比如请求头中有个header叫token,放置了认证后的请求头String token = request.getHeader("token");log.info("用户token:{}", token);if (StringUtils.hasText(token)) {// 验证token是否已经登录了的用户的token,用户的token临时放在了LoginControllerUserDetails userDetails = LoginController.TOKEN_USERNAME.get(token);if (Objects.nonNull(userDetails)) {// 有,表示token是对的,设置线程上下文认证信息,然后访问其他资源时,security就会放行UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);}}filterChain.doFilter(request, response);}
}
验证效果
未认证前访问首页:


登录认证:

认证成功后,把得到的token放入请求头中,再请求


相关文章:
Spring Security 简单token配置
Spring Security 简单token配置 说明:非表单配置 先上码: https://gitee.com/qkzztx_admin/security-demo/tree/master/demo-two 环境:win10 idea2023 springboot2.7.6 maven3.8.6 代码清单说明 依赖: <dependency><…...
2023 “华为杯” 中国研究生数学建模竞赛(F题)深度剖析|数学建模完整代码+建模过程全解全析
F题代码思路 当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2021年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。 让我们一起看看研赛的F题呀!全文都已…...
FFmpeg 命令:从入门到精通 | ffplay 简单过滤器
FFmpeg 命令:从入门到精通 | ffplay 简单过滤器 FFmpeg 命令:从入门到精通 | ffplay 简单过滤器视频旋转视频反转视频旋转和反转音频变速播放视频变速播放音视频同时变速更多参考 FFmpeg 命令:从入门到精通 | ffplay 简单过滤器 本节介绍了简…...
应用在手机触摸屏中的电容式触摸芯片
触控屏(Touch panel)又称为触控面板,是个可接收触头等输入讯号的感应式液晶显示装置,当接触了屏幕上的图形按钮时,屏幕上的触觉反馈系统可根据预先编程的程式驱动各种连结装置,可用以取代机械式的按钮面板&…...
计算机网络之传输层
计算机网络 - 传输层 计算机网络 - 传输层 UDP 和 TCP 的特点UDP 首部格式TCP 首部格式TCP 的三次握手TCP 的四次挥手TCP 可靠传输TCP 滑动窗口TCP 流量控制TCP 拥塞控制 1. 慢开始与拥塞避免2. 快重传与快恢复 网络层只把分组发送到目的主机,但是真正通信的并不是…...
vue下载在前端存放的pdf文件
vue下载在前端存放的pdf文件 注意,这里要在public文件夹中新建文件夹存放静态资源,不能在src文件夹中新建文件夹存放静态资源,因为public文件夹中的文件资源不会被npm run build打包编译。大家打包一下,就会发现 模板.pdf文件 是存…...
自学WEB后端05-Node.js后端服务链接数据库redis
嘿,亲爱的小伙伴们!😄 今天我要给大家分享一个超级方便且高效的 NoSQL 类型数据库——Redis!💡 它可不是一般的关系型数据库哦,而是以键值对形式存储数据的内存数据库。📚 快跟着我一起来学习如…...
【计算机网络】 基于TCP的简单通讯(客户端)
文章目录 流程伪代码代码实现加载库创建套接字连接服务端收发数据关闭套接字、卸载库 测试 流程伪代码 //1、加载库//2、创建套接字//3、连接服务端while(true){//4、发送数据//5、接收数据} //6、关闭套接字、卸载库代码实现 加载库 int err 0;WORD version MAKEWORD(2, 2…...
RabbitMQ配置
centos7安装rabbitmq 官网教程:https://www.rabbitmq.com/install-rpm.html#downloads 官网介绍了两种安装方法: 安装使用yum库中的包(强烈建议此选项)上Cloudsmith.io或PackageCloud 下载软件包并使用rpm安装它。此选项将需要手…...
火热报名中 | 2天峰会、20+热门议题,AutoESG 2023数智低碳---中国汽车碳管理创新峰会亮点抢先看!
在碳中和的背景下,减碳之风吹遍全球,而汽车行业则由于产业链长、辐射面广、碳排放总量增长快、单车碳强度高的特点,成为各国碳排放管理的监管重点,聚焦汽车业的碳博弈也逐步升级。 2020年,国务院办公厅印发的《新能源…...
机器学习——seaborn实用画图方法简介
0、seaborn简介: 前言:下面的总结只是介绍seaborn有哪些方法和属性,至于具体使用,通过下面给出的名称稍作查找即可。重点应该关注本文介绍的seaborn的使用方法seaborn与机器学习的关系: 知识图谱 0.1、了解即可的知识: seaborn:在matplotlib的基础上画一些更好看的图,在…...
leetCode 188.买卖股票的最佳时机 IV 动态规划 + 状态压缩
给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。 注意:你不能同时参与多…...
Lua学习笔记:debug.sethook函数
前言 本篇在讲什么 使用Lua的debug.setHook函数 本篇需要什么 对Lua语法有简单认知 依赖Sublime Text工具 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容 ★提高阅读体验★ 👉 ♠ 一级标题 &…...
信息化发展74
产业数字化 产业数字化是指在新一代数字科技支撑和引领下,以数据为关键要素,以价值释放为核心,以数据赋能为主线,对产业链上下游的全要素数字化升级、转型和再造的过程。产业数字化作为实现数字经济和传统经济深度融合发展的重要…...
Go-Ldap-Admin | openLDAP 同步钉钉、企业微信、飞书组织架构实践和部分小坑
目录 一、Docker-compose快速拉起demo测试环境 二、原生部署流程 安装MySQL:5.7数据库 安装openLDAP 修改域名,新增con.ldif 创建一个组织 安装OpenResty 下载后端 下载前端 部署后端 部署前端 三、管理动态字段 钉钉 企业微信 飞书 四、…...
elasticsearch+logstash+kibana整合(ELK的使用)第一课
一、安装elasticsearch 0、创建目录,统一放到/data/service/elk 1、下载安装包 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.1.0-linux-x86_64.tar.gz2、解压 tar -xzvf elasticsearch-7.1.0-linux-x86_64.tar.gz3、新建用户和组…...
宝塔 php修改了php.ini配置不生效
最近在使用hypref,php的版本是7.4 服务器linux,用宝塔安装完php,并装完swoole插件后 安装了swoole后,需要在php.ini中修改一下配置文件 添加 swoole.use_shortnameOff 但是添加了,重启php,依然不生效 解决方法是: 同时…...
Unrecognized option ‘stream_loop‘.(版本不匹配,利用make编译安装)
执行如下命令: ffmpeg -re -stream_loop -1 -i 1.mp4 -vcodec copy -acodec copy -f rtsp -rtsp_transport tcp rtsp://localhost:8554/live1.sdp报如下错误:Unrecognized option ‘stream_loop’. 查看ffmpeg版本:ffmpeg -version 显示&am…...
【考研数学】概率论与数理统计 —— 第三章 | 二维随机变量及其分布(2,常见的二维随机变量及二维变量的条件分布和独立性)
文章目录 引言四、常见的二维随机变量4.1 二维均匀分布4.2 二维正态分布 五、二维随机变量的条件分布5.1 二维离散型随机变量的条件分布律5.2 二维连续型随机变量的条件分布 六、随机变量的独立性6.1 基本概念6.2 随机变量独立的等价条件 写在最后 引言 有了上文关于二维随机变…...
力扣 -- 10. 正则表达式匹配
解题步骤: 参考代码: class Solution { public:bool isMatch(string s, string p) {int ms.size();int np.size();//处理后续映射关系s s;//处理后续映射关系p p;vector<vector<bool>> dp(m1,vector<bool>(n1));//初始化dp[0][0]true…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
