SpringSecurity+jwt使用
参考文章链接
自定义SpringSecurity用户
package com.daben.springsecurityjwt.vo;import com.daben.springsecurityjwt.entity.SysUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
/*** SpringSecurity用户** @Author JinDongSheng* @Date 2023-11-16 09:21*/
public class SpringSecurityUser extends User {/*** 系统用户*/private SysUser sysUser;/*** 构造函数*/public SpringSecurityUser(SysUser sysUser, Collection<? extends GrantedAuthority> authorities) {super(sysUser.getUsername(), sysUser.getPassword(), authorities);this.sysUser = sysUser;}public SysUser getSysUser() {return sysUser;}public void setSysUser(SysUser sysUser) {this.sysUser = sysUser;}
}
自定义认证失败处理类
package com.daben.springsecurityjwt.handle;import com.alibaba.fastjson2.JSON;
import com.daben.springsecurityjwt.vo.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*** 未登录处理类** @Author JinDongSheng* @Date 2023-11-15 17:37*/
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {response.setStatus(200);response.setContentType("application/json");response.setCharacterEncoding("utf-8");response.getWriter().print(JSON.toJSONString(Result.error("认证失败,无法访问系统资源!")));}
}
自定义Security用户服务实现类
package com.daben.springsecurityjwt.service;import com.daben.springsecurityjwt.entity.SysUser;
import com.daben.springsecurityjwt.vo.SpringSecurityUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collections;
/*** Security用户服务实现类** @Author JinDongSheng* @Date 2023-11-16 09:14*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate SysUserServiceImpl sysUserServiceImpl;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 根据用户名称查询用户SysUser sysUser = sysUserServiceImpl.selectSysUserByName(username);// 查询用户权限List<GrantedAuthority> authorities = Collections.emptyList();// 返回Security指定的用户对象return new SpringSecurityUser(sysUser, authorities);}
}
自定义JWT工具类
package com.daben.springsecurityjwt.utils;import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.daben.springsecurityjwt.entity.SysUser;
import io.jsonwebtoken.*;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
/*** JWT工具类** @Author JinDongSheng* @Date 2023-11-16 15:49*/
public class JwtUtil {/*** Token有效期为30分钟*/public static final int EXPIRE_TIME = 30;/*** 秘钥*/private final static String SECRET_KEY = "ABCDE";/*** 生成token*/public static String createToken(SysUser user) {return Jwts.builder()// 将user放进JWT.setSubject(JSONUtil.toJsonStr(user))// 设置过期时间.setExpiration(DateUtil.offsetMinute(new Date(), EXPIRE_TIME))// 设置加密算法和秘钥.signWith(SignatureAlgorithm.HS512, SECRET_KEY).compact();}public static Claims parseToken(String token) {// 如果是空字符串直接返回nullif (StringUtils.isEmpty(token)) {return null;}// 这个Claims对象包含了许多属性,比如签发时间、过期时间以及存放的数据等Claims claims = null;// 解析失败了会抛出异常,所以我们要捕捉一下。token过期、token非法都会导致解析失败try {claims = Jwts.parser().setSigningKey(SECRET_KEY) // 设置秘钥.parseClaimsJws(token).getBody();} catch (JwtException e) {// 这里应该用日志输出,为了演示方便就直接打印了System.err.println("解析失败!");}return claims;}
}
自定义token认证过滤器
package com.daben.springsecurityjwt.filter;import cn.hutool.json.JSONUtil;
import com.daben.springsecurityjwt.entity.SysUser;
import com.daben.springsecurityjwt.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
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.Collections;
/*** 登录过滤器** @Author JinDongSheng* @Date 2023-11-16 14:48*/
@Component
public class LoginFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 解析tokenClaims claims = JwtUtil.parseToken(request.getHeader("Authorization"));if (claims != null) {// 获取用户SysUser sysUser = JSONUtil.toBean(claims.getSubject(), SysUser.class);// 手动组装一个认证对象Authentication authentication = new UsernamePasswordAuthenticationToken(sysUser, null, Collections.emptyList());// 将认证对象放到上下文中SecurityContextHolder.getContext().setAuthentication(authentication);}filterChain.doFilter(request, response);}
}
自定义SpringSecurity配置类
package com.daben.springsecurityjwt.config;import com.daben.springsecurityjwt.filter.LoginFilter;
import com.daben.springsecurityjwt.handle.AuthenticationEntryPointImpl;
import com.daben.springsecurityjwt.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/*** spring security 配置** @Author JinDongSheng* @Date 2023-11-15 17:16*/
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {/*** 登录认证过滤器*/@Autowiredprivate LoginFilter loginFilter;/*** Security用户服务实现类*/@Autowiredprivate UserDetailsServiceImpl userDetailsService;/*** 未登录处理类*/@Autowiredprivate AuthenticationEntryPointImpl authenticationEntryPoint;@Overrideprotected void configure(HttpSecurity http) throws Exception {// 关闭csrfhttp.csrf().disable();// 关闭frameOptionshttp.headers().frameOptions().disable();// 指定未登录处理类http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);// 前置登录认证过滤器http.addFilterBefore(loginFilter, UsernamePasswordAuthenticationFilter.class);// 禁用sessionhttp.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);// 配置认证和授权接口http.authorizeRequests()// 指出放行接口.antMatchers("/sys/port/*").permitAll()// 拦截剩余接口.anyRequest().authenticated();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 指定UserDetailService和加密器auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Beanpublic PasswordEncoder passwordEncoder() {// 使用bcrypt加密return new BCryptPasswordEncoder();}
}
登录入口
package com.daben.springsecurityjwt.controller;import com.daben.springsecurityjwt.entity.SysUser;
import com.daben.springsecurityjwt.utils.JwtUtil;
import com.daben.springsecurityjwt.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/*** 登录控制器** @Author JinDongSheng* @Date 2023-11-15 17:25*/
@RestController
@RequestMapping("/sys/port")
public class SysPortController {@Autowiredprivate AuthenticationManager authenticationManager;@PostMapping("/login")public Result login(@RequestBody SysUser sysUser) {// 认证Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword()));if (authenticate.isAuthenticated()) {// 生成tokenString token = JwtUtil.createToken(sysUser);// 返回tokenreturn Result.success(token);}return Result.error("用户名或密码错误");}
}
整体调用流程
- 服务启动,根据【自定义SpringSecurity配置类】配置信息(指定放行和认证接口、token认证过滤器、认证失败处理器、密码加密器、用户查询服务等。)
- 用户发起登录请求。
- token认证过滤器过滤,因为不携带token,直接放行调用登录接口,在登录接口中手动调用AuthenticationManager进行用户信息认证。
- AuthenticationManager进行用户信息认证时会调用【自定义Security用户服务实现类】查询数据库用户,然后将数据库用户封装成Security指定用户返回。
- 认证失败调用【自定义认证失败处理类】,认证成功则返回token
- 用户发起非登录请求,token过滤器过滤,token校验成功将认证对象放入上下文中。调用请求接口。token校验失败,调用【自定义认证失败处理类】。
pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.vitalframework</groupId><artifactId>vital-framework-dependencies</artifactId><version>1.1.0</version></parent><groupId>com.citic</groupId><artifactId>vital-portal-core</artifactId><version>1.0.0</version><name>vital-portal-core</name><description>系统管理(门面工程)模块</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.rep4orting.outputEncoding>UTF-8</project.rep4orting.outputEncoding><java.version>1.8</java.version><maven.compiler.source>${java.version}</maven.compiler.source><maven.compiler.target>${java.version}</maven.compiler.target></properties><dependencies><!--CITIC 一些公共包--><dependency><groupId>com.vitalframework.web</groupId><artifactId>vital-framework-web-common</artifactId><version>1.0.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId></dependency><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId></dependency><dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId></dependency><!--代码生成器--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId></dependency><dependency><groupId>org.codehaus.castor</groupId><artifactId>castor-xml</artifactId></dependency></dependencies><build>
<!-- <finalName>${project.artifactId}</finalName>--><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork><skip>true</skip></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>${maven-source-plugin.version}</version></plugin></plugins></build>
</project>
相关文章:
SpringSecurity+jwt使用
参考文章链接 自定义SpringSecurity用户 package com.daben.springsecurityjwt.vo;import com.daben.springsecurityjwt.entity.SysUser; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import j…...

html-网站菜单-点击显示导航栏
一、效果图 1.点击显示菜单栏,点击x号关闭; 2.点击一级菜单,展开显示二级,并且加号变为减号; 3.点击其他一级导航,自动收起展开的导航。 二、代码实现 <!DOCTYPE html> <html><head>&…...
【C++函数的进化】函数指针,模板,仿函数,lambda表达式
/*** poject * author jUicE_g2R(qq:3406291309)* file C函数的进化* * language C* EDA Base on VS2022* editor Obsidian(黑曜石笔记软件)* * copyright 2023* COPYRIGHT 原创学习笔记:转载需获得博…...

云服务器windows service2022 部署git服务器
1 安装 下载地址gitblit 解压到你的一个目录,我这里给的是C:\gitblit 根据官网提示要下载jre or jdk7.0,这里建议使用下载jre (jdk 有时候运行出问题,或者2个都安装),自行安装java,这里不做环境配置的说明 进入c:\gitblit\data 目录里面找到,defaults.properties 文件,编辑主…...
Linux_Docker修改Docker Root Dir
今天遇到需求,要修改一下docker容器和镜像的存储位置,默认位置为/var/lib/docker目录下,要修改到/new/dockerFile目录下。 停止docker服务 sudo service docker stop 备份docker容器镜像 移动/var/lib/docker目录下的文件到/dockerFile目录…...

解决requests 2.28.x版本SSL错误:证书验证失败
1、问题背景 在使用requests 2.28.1版本时,我进行HTTP post传输报告负载时,由于SSL验证设置为True,请求失败,错误如下:(Caused by SSLError(SSLCertVerificationError(1, ‘[SSL: CERTIFICATE_VERIFY_FAILED] certifi…...

【开源】基于Vue.js的开放实验室管理系统的设计和实现
项目编号: S 013 ,文末获取源码。 \color{red}{项目编号:S013,文末获取源码。} 项目编号:S013,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实…...
使用composer安装ffmpeg的步骤
以下是使用composer安装ffmpeg的步骤: 1.在laravel根目录下执行以下命令安装ffmpeg: composer require php-ffmpeg/php-ffmpeg 2.如果不指定版本号,则默认使用0.14版本。 3.执行以上命令后,composer会自动下载并安装ffmpeg。 …...
RT-DETR优化策略:轻量级Backbone改进 | 高效模型 (Efficient MOdel, EMO),现代倒残差移动模块设计|ICCV2023
🚀🚀🚀本文改进:面向移动端的轻量化网络模型——EMO,它能够以相对较低的参数和 FLOPs 超越了基于 CNN/Transformer 的 SOTA 模型,支持四个版本EMO_1M, EMO_2M, EMO_5M, EMO_6M,参数量如下,相对于自带的rtdetr-l、rtdetr-x有很大提升 layersparametersgradientsEMO_1…...
一些nginx命令
1.停止nginx nginx -s quit systemctl stop nginx.service 立即停止 nginx-s stop 杀死nginx进程 killall nginx 2.启动命令 nginx systemctl start nginx.service 3.查看nginx进程 ps aux | grep nginx 4.重启nginx服务 systemctl restart nginx.service 5.重载…...
WPF自定义控件介绍
在WPF中,自定义控件通常是指从头开始创建一个新控件或从现有控件继承并扩展其功能。自定义控件与用户控件(User Control)不同,用户控件是通过组合其他控件来构建的,而自定义控件通常涉及对控件的更底层的渲染和行为进行…...

JUNIT使用和注意、以及断言的介绍使用、SpringBoot Test测试类的使用、maven配置使用junit详细介绍
参考文章: https://www.cnblogs.com/zhukaile/p/14514238.html,https://blog.csdn.net/qq_36448800/article/details/126438339 一、什么是单元测试 在平时的开发当中,一个项目往往包含了大量的方法,可能有成千上万个。如何去保…...

强化学习在文生图中的应用:Training Diffusion Models with Reinforcement Learning
论文链接:Training Diffusion Models with Reinforcement Learning项目地址:Training Diffusion Models with Reinforcement Learning官方代码:https://github.com/kvablack/ddpo-pytorch/tree/maintrl实现:https://huggingface.co/docs/trl/ddpo_trainer🤗关注公众号 fu…...

【C语言】数组下标为啥从0开始?下标越界访问一定报错吗?
本篇文章目录 0. 相关文章1. 下标从0开始问题2. 数组下标越界不报错问题 0. 相关文章 指针与指针变量数组名不是首元素地址的的2个例外拨开指针和数组名之间的迷雾 1. 下标从0开始问题 原因是:数组下标访问本质是“指针解引用操作”,而指针又是地址&am…...

机器学习-搜索技术:从技术发展到应用实战的全面指南
在本文中,我们全面探讨了人工智能中搜索技术的发展,从基础算法如DFS和BFS,到高级搜索技术如CSP和优化问题的解决方案,进而探索了机器学习与搜索的融合,最后展望了未来的趋势和挑战,提供了对AI搜索技术深刻的…...
Axelar、J.P.Morgan Onyx、Apollo 完成概念验证,向跨区块链自动化投资领域探索
J.P.Morgan Onyx、Apollo、Axelar、Oasis Pro 以及 Provenance Block Chain 展开合作,共同进行互操作性概念验证(Proof-of-Concept,PoC)。 新加坡 — Axelar Inc.、Oasis Pro 、Provenance Blockchain 与 J.P.Morgan Onyx 以及 Apollo 通过新…...

wpf devexpress添加TreeListControl到项目
此教程示范如何添加TreeListControl到项目和绑定控件自引用数据源: 添加数据模型 绑定tree,并添加如下字段到数据源对象: Key字段包含唯一值索引节点 Parent字段包含父索引节点 添加数据模型(Employee和Staff类)到…...

WPF创建自定义控件编译通过但是找不到资源
报错: 原因: 路径写错了: 不是这样: Source"pack://application:,,,/Controls/Styles/xTabControl.xaml" 而是这样: Source"pack://application:,,,/项目名;component/Controls/Styles/xTabControl.xaml …...

PHP 中传值与传引用的区别,什么时候传值什么时候传引用?
传值:当使用传值的方式时,函数或方法会创建原始变量的一个副本,并将该副本传递给函数或方法。在函数或方法内部,对副本的任何修改都不会影响到原始变量。当函数或方法执行完毕后,副本被销毁,不再使用。 传引…...

es安装方式
es安装方式 1.下载镜像的方式 分词器 kibana和es和容器互通的方式 docker network create es-net开始拉去镜像的方式 docker pull kibana:7.12.1运行镜像的方式 docker run -d \--name es \-e "ES_JAVA_OPTS-Xms512m -Xmx512m" \-e "discovery.typesingle-…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...