图书馆项目

项目已经集成了springsecurity并已上传

以下代码看看就好了gitee上有完整代码

添加的依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version> <!-- 或更高版本 --></dependency><dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.1</version> <!-- 或更高版本 --></dependency><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.8.1</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version></dependency>

utils工具类

EmptyUtil

/*** 判断对象是否为空的工具类*/
public abstract class EmptyUtil {/**** 对string字符串是否为空判断** @param str 被判定字符串* @return*/public static boolean isNullOrEmpty(String str) {if (str == null || "".equals(str.trim()) || "null".equalsIgnoreCase(str.trim()) || "undefined".equalsIgnoreCase(str.trim())) {return true;} else {return false;}}/****  对于StringBuffer类型的非空判断** @param str 被判定StringBuffer* @return*/public static boolean isNullOrEmpty(StringBuffer str) {return (str == null || str.length() == 0);}/****  对于string数组类型的非空判断** @param str 被判定字符串数组* @return*/public static boolean isNullOrEmpty(String[] str) {if (str == null || str.length == 0) {return true;} else {return false;}}/****  对于Object类型的非空判断** @param obj 被判定对象* @return*/public static boolean isNullOrEmpty(Object obj) {if (obj == null || "".equals(obj)) {return true;} else {return false;}}/****  对于Object数组类型的非空判断** @param obj 被判定对象数组* @return*/public static boolean isNullOrEmpty(Object[] obj) {if (obj == null || obj.length == 0) {return true;} else {return false;}}/****  对于Collection类型的非空判断** @param collection 被判定Collection类型对象* @return*/public static boolean isNullOrEmpty(Collection collection) {if (collection == null || collection.isEmpty()) {return true;} else {return false;}}/*** @方法名:对于Map类型的非空判断* @功能说明:对于Map类型的非空判断* @return boolean true-为空,false-不为空* @throws*/@SuppressWarnings("rawtypes")public static boolean isNullOrEmpty( Map map) {if (map == null || map.isEmpty()) {return true;} else {return false;}}/**** @方法名:removeNullUnit* @功能说明: 删除集合中的空元素* @return*/public static <T> List<T> removeNullUnit(List<T> xllxList) {List<T> need = new ArrayList<T>();for (int i = 0; i < xllxList.size(); i++) {if (!isNullOrEmpty(xllxList.get(i))) {need.add(xllxList.get(i));}}return need;}}

JWTUtil

public class JwtUtil {/*** 生成jwt* 使用Hs256算法, 私匙使用固定秘钥** @param secretKey jwt秘钥* @param dateOffset jwt过期时间(小时)* @param claims    设置的信息* @return*/public static String createJWT(String secretKey , int dateOffset, Map<String, Object> claims) {// 指定签名的时候使用的签名算法,也就是header那部分SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;// 设置jwt的bodyJwtBuilder builder = Jwts.builder()// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setClaims(claims)// 设置签名使用的签名算法和签名使用的秘钥.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))// 设置过期时间.setExpiration(DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, dateOffset));return builder.compact();}/*** Token解密** @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个* @param token     加密后的token* @return*/public static Claims parseJWT(String secretKey, String token) {try {// 得到DefaultJwtParserClaims claims = Jwts.parser()// 设置签名的秘钥.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))// 设置需要解析的jwt.parseClaimsJws(token).getBody();return claims;} catch (Exception e) {
//            throw new AccessDeniedException("没有权限,请登录");throw new RuntimeException("没有权限,请登录");}}}

权限管理核心配置类

@EnableWebSecurity
@Configuration
public class SecurityConfig  {@AutowiredJwtAuthorizationManager jwtAuthorizationManager;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests().antMatchers("/security/login").permitAll().antMatchers("/doc.html", "/webjars/**", "/swagger-resources/**", "/v2/api-docs").permitAll().anyRequest().access(jwtAuthorizationManager);http.csrf().disable();http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS );//关闭sessionhttp.headers().cacheControl().disable();//关闭缓存return http.build();}@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {return  authenticationConfiguration.getAuthenticationManager();}/*** BCrypt密码编码* @return*/@Beanpublic BCryptPasswordEncoder bcryptPasswordEncoder() {return new BCryptPasswordEncoder();}}

登录接口

/***  登录接口*/
@RestController
@Api(tags = "用户登录")
@RequestMapping("security")
public class LoginController {@AutowiredILoginService loginService;@PostMapping("/login")@ApiOperation(value = "用户登录",notes = "用户登录")@ApiImplicitParam(name = "userDto",value = "登录对象",required = true,dataType = "UserDto")public Result<UserVo> login(@RequestBody UserDto userDto){return Result.success(loginService.login(userDto));}
}

LoginServiceImpl

@Service
public class LoginServiceImpl implements ILoginService {@AutowiredAuthenticationManager authenticationManager;@Autowiredprivate JwtTokenManagerProperties jwtTokenManagerProperties;@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic UserVo login(UserDto userDto) {UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDto.getUsername(), userDto.getPassword());Authentication authenticate = authenticationManager.authenticate(authentication);UserAuth userAuth=(UserAuth)authenticate.getPrincipal();userAuth.setPassword("");UserVo userVoResult= BeanUtil.copyProperties(userAuth, UserVo.class);//userToken令牌颁布String userToken = UUID.randomUUID().toString();userVoResult.setUserToken(userToken);//构建载荷Map<String, Object> claims = new HashMap<>();String userVoJsonString = JSONObject.toJSONString(userVoResult);claims.put("currentUser", userVoJsonString);//jwtToken令牌颁布String jwtToken = JwtUtil.createJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), jwtTokenManagerProperties.getTtl(), claims);//剔除缓存:用户关联userTokenString userTokenKey = UserCacheConstant.USER_TOKEN + userDto.getUsername();long ttl = Long.valueOf(jwtTokenManagerProperties.getTtl()) / 1000;//key:username   value:uuidredisTemplate.opsForValue().set(userTokenKey, userToken, ttl, TimeUnit.SECONDS);//续期缓存:userToken关联jwtTokenString jwtTokenKey = UserCacheConstant.JWT_TOKEN + userToken;//key:uuid   value:jwttokenredisTemplate.opsForValue().set(jwtTokenKey, jwtToken, ttl, TimeUnit.SECONDS);return userVoResult;}
}

JwtAuthorizationManager

@Slf4j
@Component
public class JwtAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {private AntPathMatcher antPathMatcher = new AntPathMatcher();@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate JwtTokenManagerProperties jwtTokenManagerProperties;@Overridepublic AuthorizationDecision check(Supplier<Authentication> authentication,RequestAuthorizationContext requestAuthorizationContext) {//用户当前请求路径String method = requestAuthorizationContext.getRequest().getMethod();String requestURI = requestAuthorizationContext.getRequest().getRequestURI();String targetUrl = (method+requestURI);//获得请求中的认证后传递过来的userTokenString userToken = requestAuthorizationContext.getRequest().getHeader("authorization");//如果userToken为空,则当前请求不合法if (EmptyUtil.isNullOrEmpty(userToken)){return new AuthorizationDecision(false);}//通过userToken获取jwtTokenString jwtTokenKey = UserCacheConstant.JWT_TOKEN+userToken;//key:uuidString jwtToken = redisTemplate.opsForValue().get(jwtTokenKey);//如果jwtToken为空,则当前请求不合法if (EmptyUtil.isNullOrEmpty(jwtToken)){return new AuthorizationDecision(false);}//校验jwtToken是否合法Claims cla = JwtUtil.parseJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), jwtToken);if (ObjectUtil.isEmpty(cla)) {//token失效return new AuthorizationDecision(false);}//如果校验jwtToken通过,则获得userVo对象UserVo userVo = JSONObject.parseObject(String.valueOf(cla.get("currentUser")),UserVo.class);//用户剔除校验:redis中最新的userToken与出入的userToken不符合,则认为当前用户被后续用户剔除//key:username  value:uuidString currentUserToken = redisTemplate.opsForValue().get(UserCacheConstant.USER_TOKEN + userVo.getUsername());if (!userToken.equals(currentUserToken)){return new AuthorizationDecision(false);}//如果当前UserToken存活时间少于10分钟,则进行续期Long remainTimeToLive = redisTemplate.opsForValue().getOperations().getExpire(jwtTokenKey);if (remainTimeToLive.longValue()<= 600){//jwt生成的token也会过期,所以需要重新生成jwttokenMap<String, Object> claims = new HashMap<>();String userVoJsonString = String.valueOf(cla.get("currentUser"));claims.put("currentUser", userVoJsonString);//jwtToken令牌颁布String newJwtToken = JwtUtil.createJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), jwtTokenManagerProperties.getTtl(), claims);long ttl = Long.valueOf(jwtTokenManagerProperties.getTtl()) / 1000;redisTemplate.opsForValue().set(jwtTokenKey, newJwtToken, ttl, TimeUnit.SECONDS);redisTemplate.expire(UserCacheConstant.USER_TOKEN + userVo.getUsername(), ttl, TimeUnit.SECONDS);}//TODO 判断当前用户是否拥有当前URL权限 以及见表(不太想写好麻烦啊,好累)//当前用户资源是否包含当前URL/*for (String resourceRequestPath : userVo.getResourceRequestPaths()) {boolean isMatch = antPathMatcher.match(resourceRequestPath, targetUrl);if (isMatch){log.info("用户:{}拥有targetUrl权限:{}==========",userVo.getUsername(),targetUrl);return new AuthorizationDecision(true);}return new AuthorizationDecision(false);}*/return new AuthorizationDecision(true);}}

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

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

相关文章

【6.2】位运算-解重复的DNA序列

一、题目 所有 DNA 都 由 一 系 列 缩 写 为 A &#xff0c; C &#xff0c; G 和 T 的 核 苷 酸 组 成 &#xff0c; 例如&#xff1a;"ACGAAT TCCG"。在研究DNA时&#xff0c;识别DNA中的重复序列有时会对研究非常有 帮助。 编写一个函数来找出所有目标子串&#…

Net.Core Mvc 添加 log 日志

1: 首先在 Nuget 安装插件 2&#xff1a;添加 log 配置 在项目中新创件一个文件夹 ConfigFile 在文件家里面添加 log4net.config log4net.config 里面写入 <?xml version"1.0" encoding"utf-8"?> <configuration><log4net><!--跟…

A030-基于Spring boot的公司资产网站设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…

AG32 MCU与CPLD通过AHB总线交互

MCU与CPLD可以通过AHB或APB总线进行数据交互。APB总线通常连接低速设备&#xff0c;如串口&#xff0c;而AHB总线则用于连接高速设备&#xff0c;如RAM等。由于我们需要高速采集大量数据&#xff0c;因此选择使用AHB总线与CPLD进行交互。 地址范围 在地址设计中&#xff0c;C…

【学习笔记】PT协程-未完待续

单线程编程-协程 单线程&#xff0c;所有协程都是共享栈–换句话说&#xff1a;裸机 代码结构 十分精简 lc 有两个版本 文件说明lc-addrlabels.h使用GCC扩展语法实现的协程基础lc-switch.h使用switch语句实现的协程基础lc.h用于选择GCC语法还是switch语句实现pt.h基于lc.h实…

【python系列】python内置函数print()和input()

1.前言 正式开始学习python编程基础知识&#xff0c;首先要建立正确的学习姿势&#xff0c;什么姿势呢&#xff0c;当然不是躺着。首先要学会看语法&#xff0c;学习每一个内置函数都要先把语法和语义理解&#xff0c;再结合勤于练习。有些同学可能英语不太好&#xff0c;这里…

并发基础:(淘宝笔试题)三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串

🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀 🌟 在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。 💡 无论你是刚刚踏…

字节、快手、Vidu“打野”升级,AI视频小步快跑

文&#xff5c;白 鸽 编&#xff5c;王一粟 继9月份版本更新之后&#xff0c;光锥智能从生数科技联合创始人兼CEO唐家渝朋友圈获悉&#xff0c;Vidu大模型将于本周再次进行版本升级&#xff0c;Vidu-1.5版本即将上线。 此版本更新方向仍是重点延伸大模型的泛化能力和主体…

redis实现消息队列的几种方式

一、了解 众所周知&#xff0c;redis是我们日常开发过程中使用最多的非关系型数据库&#xff0c;也是消息中间件。实际上除了常用的rabbitmq、rocketmq、kafka消息队列&#xff08;大家自己下去研究吧~模式都是通用的&#xff09;&#xff0c;我们也能使用redis实现消息队列。…

JVM(一、基础知识)

JVM虚拟机的灵魂三问 JVM是什么&#xff1f; 广义上是一种规范&#xff0c;狭义上的是JDK中的JVM虚拟机&#xff0c;虚拟机模拟计算机的组成部分&#xff0c;可以运行我们写的应用程序&#xff0c;是对操作系统的一层抽象&#xff0c;把我们的应用程序和操作系统解耦&#xff0…

问题分析与解决:Android开机卡动画问题分析

1. 问题背景及描述 在一个android设备的开发的项目中遇到了一个比较典型的问题:在主板贴片完成后,首次刷入androdi固件验证时,遇到了按键出发开机后,系统启动到android动画界阶段时一直循环卡在此阶段,无法进入桌面。如下如所示: 此问题在许多android项目的首次点亮阶段均…

视频会议接入GB28181视频指挥调度,语音对讲方案

传统的视频会议指挥调度系统目前主流的互联网会议大部分都是私有协议&#xff0c;功能都很独立。目前主流的视频监控国标都最GB平台&#xff0c;新的需求要求融合平台要接入监控等设备&#xff0c;并能实现观看监控接入会议&#xff0c;实时语音设备指挥现场工作人员办公实施。…

跟着尚硅谷学vue2—进阶版1.0—组件化编程

2. Vue 组件化编程 1. 传统方式和使用组件方式编写的对比 1. 传统方式编写应用 2. 使用组件方式编写应用 2. 模块与组件、模块化与组件化 1. 模块 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件为什么: js 文件很多很复杂作用: 复用 js, 简化 js 的编写, 提高 j…

WebRTC视频 01 - 视频采集整体架构

一、前言&#xff1a; 我们从1对1通信说起&#xff0c;假如有一天&#xff0c;你和你情敌使用X信进行1v1通信&#xff0c;想象一下画面是不是一个大画面中有一个小画面&#xff1f;这在布局中就叫做PIP&#xff08;picture in picture&#xff09;&#xff1b;这个随手一点&am…

【大数据学习 | HBASE高级】rowkey的设计,hbase的预分区和压缩

1. rowkey的设计 ​ RowKey可以是任意字符串&#xff0c;最大长度64KB&#xff0c;实际应用中一般为10~100bytes&#xff0c;字典顺序排序&#xff0c;rowkey的设计至关重要&#xff0c;会影响region分布&#xff0c;如果rowkey设计不合理还会出现region写热点等一系列问题。 …

Spring Boot编程训练系统:架构设计与实现技巧

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理编程训练系统的相关信息成为必然。开发合适…

刘知远LLM——大模型微调:prompt-learningdelta tuning

文章目录 背景&概览Prompt-learningdelta tuning增量式指定式重参数化式 OpenPrompt工具包 对应视频P41-P57 如何高效使用大模型&#xff1f;涉及到NLP的前沿技术&#xff0c;如prompt-learning&delta tuning。 prompt-learning对学习大模型范式的改变&#xff0c;del…

Spring Boot编程训练系统:性能优化实践

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了编程训练系统的开发全过程。通过分析编程训练系统管理的不足&#xff0c;创建了一个计算机管理编程训练系统的方案。文章介绍了编程训练系统的系统分析部分&…

电子应用产品设计方案-4:基于物联网和人工智能的温度控制器设计方案

一、概述 本温度控制器旨在提供高精度、智能化、远程可控的温度调节解决方案&#xff0c;适用于各种工业和民用场景。 二、系统组成 1. 传感器模块 - 采用高精度的数字式温度传感器&#xff0c;如 TMP117&#xff0c;能够提供精确到 0.01C 的温度测量。 - 配置多个传感器分布在…

如何在 Ubuntu 24.04 上安装和配置 Fail2ban ?

确保你的 Ubuntu 24.04 服务器的安全是至关重要的&#xff0c;特别是如果它暴露在互联网上。一个常见的威胁是未经授权的访问尝试&#xff0c;特别是通过 SSH。Fail2ban 是一个强大的工具&#xff0c;可以通过自动阻止可疑活动来帮助保护您的服务器。 在本指南中&#xff0c;我…