【Springboot相关知识】Springboot结合SpringSecurity实现身份认证以及接口鉴权

Springboot结合SpringSecurity实现身份认证以及接口鉴权

    • 身份认证
      • 1. 添加依赖
      • 2. 配置JWT工具类
      • 3. 配置Spring Security
      • 4. 创建JWT请求过滤器
      • 5. 创建认证控制器
      • 6. 创建请求和响应对象
      • 7. 配置UserDetailsService
      • 8. 运行应用程序
      • 9. 测试
      • 总结
    • 接口鉴权
      • 1. 启用方法级安全注解
      • 2. 定义角色和权限
        • 示例:定义用户角色
      • 3. 使用注解进行接口鉴权
        • 1. `@PreAuthorize`
        • 2. `@PostAuthorize`
        • 3. `@Secured`
        • 4. `@RolesAllowed`
      • 4. 配置全局异常处理
      • 5. 测试接口鉴权
        • 1. 登录获取Token
        • 2. 访问受保护的接口
      • 6. 总结
    • 相关文献

身份认证

在Spring Boot中,使用Spring Security和JWT(JSON Web Token)实现身份认证和接口鉴权是一个常见的需求。下面是一个完整的示例,展示了如何实现这些功能,并支持Token刷新。

1. 添加依赖

首先,在pom.xml中添加必要的依赖:

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- JWT Library --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><!-- Spring Boot Starter Data JPA (Optional, for UserDetailsService) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- H2 Database (Optional, for testing) --><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency>
</dependencies>

2. 配置JWT工具类

创建一个JWT工具类,用于生成和解析JWT Token。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;@Component
public class JwtUtil {private String SECRET_KEY = "secret";// 生成Tokenpublic String generateToken(UserDetails userDetails) {Map<String, Object> claims = new HashMap<>();return createToken(claims, userDetails.getUsername());}// 创建Tokenprivate String createToken(Map<String, Object> claims, String subject) {return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10小时有效期.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}// 验证Tokenpublic Boolean validateToken(String token, UserDetails userDetails) {final String username = extractUsername(token);return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));}// 提取用户名public String extractUsername(String token) {return extractClaim(token, Claims::getSubject);}// 提取过期时间public Date extractExpiration(String token) {return extractClaim(token, Claims::getExpiration);}// 提取Claimpublic <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {final Claims claims = extractAllClaims(token);return claimsResolver.apply(claims);}// 提取所有Claimprivate Claims extractAllClaims(String token) {return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();}// 判断Token是否过期private Boolean isTokenExpired(String token) {return extractExpiration(token).before(new Date());}
}

3. 配置Spring Security

创建一个Spring Security配置类,配置身份认证和接口鉴权。

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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtRequestFilter jwtRequestFilter;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/authenticate", "/refreshToken").permitAll() // 允许匿名访问的接口.anyRequest().authenticated() // 其他接口需要认证.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 无状态会话http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);}@Beanpublic PasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance(); // 仅用于示例,生产环境应使用BCryptPasswordEncoder}@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}

4. 创建JWT请求过滤器

创建一个过滤器,用于在每次请求中验证JWT Token。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
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;@Component
public class JwtRequestFilter extends OncePerRequestFilter {@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtUtil jwtUtil;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {final String authorizationHeader = request.getHeader("Authorization");String username = null;String jwt = null;if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {jwt = authorizationHeader.substring(7);username = jwtUtil.extractUsername(jwt);}if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);if (jwtUtil.validateToken(jwt, userDetails)) {UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);}}chain.doFilter(request, response);}
}

5. 创建认证控制器

创建一个控制器,用于处理用户登录和Token刷新。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;@RestController
public class AuthenticationController {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtUtil jwtUtil;@PostMapping("/authenticate")public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {try {authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));} catch (Exception e) {throw new Exception("Incorrect username or password", e);}final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());final String jwt = jwtUtil.generateToken(userDetails);return ResponseEntity.ok(new AuthenticationResponse(jwt));}@PostMapping("/refreshToken")public ResponseEntity<?> refreshAuthenticationToken(@RequestHeader("Authorization") String oldToken) {String username = jwtUtil.extractUsername(oldToken.substring(7));UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (jwtUtil.validateToken(oldToken.substring(7), userDetails)) {String newToken = jwtUtil.generateToken(userDetails);return ResponseEntity.ok(new AuthenticationResponse(newToken));}return ResponseEntity.badRequest().body("Invalid token");}
}

6. 创建请求和响应对象

创建用于封装请求和响应的对象。

public class AuthenticationRequest {private String username;private String password;// Getters and Setters
}public class AuthenticationResponse {private final String jwt;public AuthenticationResponse(String jwt) {this.jwt = jwt;}public String getJwt() {return jwt;}
}

7. 配置UserDetailsService

实现UserDetailsService接口,用于加载用户信息。

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.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.ArrayList;@Service
public class MyUserDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 这里可以从数据库中加载用户信息return new User("user", "password", new ArrayList<>());}
}

8. 运行应用程序

现在,你可以运行Spring Boot应用程序,并通过以下接口进行测试:

  • 登录接口: POST /authenticate
  • 刷新Token接口: POST /refreshToken
  • 受保护的接口: 任何其他接口都需要在请求头中添加Authorization: Bearer <token>

9. 测试

你可以使用Postman或curl等工具进行测试:

  • 登录请求:

    POST /authenticate
    {"username": "user","password": "password"
    }
    
  • 刷新Token请求:

    POST /refreshToken
    Authorization: Bearer <old_token>
    

总结

通过以上步骤,我们实现了一个基于Spring Security和JWT的身份认证和接口鉴权系统,并支持Token刷新。你可以根据实际需求进一步扩展和优化这个系统。

接口鉴权

在Spring Security中,接口鉴权通常通过配置HttpSecurity来实现。我们可以使用注解(如@PreAuthorize@PostAuthorize@Secured等)来细粒度地控制接口的访问权限。以下是接口鉴权的详细实现和示例。


1. 启用方法级安全注解

在Spring Boot中,默认情况下方法级安全注解是关闭的。我们需要在配置类中启用它。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,  // 启用@PreAuthorize和@PostAuthorize注解securedEnabled = true,  // 启用@Secured注解jsr250Enabled = true    // 启用@RolesAllowed注解
)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}

2. 定义角色和权限

在Spring Security中,角色和权限通常通过UserDetails实现类来定义。我们可以为用户分配角色或权限,然后在接口上使用注解进行鉴权。

示例:定义用户角色

UserDetailsService中,为用户分配角色:

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.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.Arrays;@Service
public class MyUserDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {if ("admin".equals(username)) {return new User("admin", "password", Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));} else if ("user".equals(username)) {return new User("user", "password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));} else {throw new UsernameNotFoundException("User not found with username: " + username);}}
}

3. 使用注解进行接口鉴权

Spring Security提供了多种注解来实现接口鉴权。以下是常用的注解及其用法:

1. @PreAuthorize

在方法执行前进行权限检查。

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 只有ADMIN角色可以访问@GetMapping("/admin")@PreAuthorize("hasRole('ADMIN')")public String adminEndpoint() {return "Hello Admin!";}// 只有USER角色可以访问@GetMapping("/user")@PreAuthorize("hasRole('USER')")public String userEndpoint() {return "Hello User!";}// 同时支持ADMIN和USER角色@GetMapping("/all")@PreAuthorize("hasAnyRole('ADMIN', 'USER')")public String allEndpoint() {return "Hello All!";}// 自定义权限表达式@GetMapping("/custom")@PreAuthorize("hasAuthority('READ_PRIVILEGE')")public String customEndpoint() {return "Custom Access!";}
}
2. @PostAuthorize

在方法执行后进行权限检查。

import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 方法执行后检查返回值@GetMapping("/postAuth")@PostAuthorize("returnObject == 'Hello Admin!'")public String postAuthEndpoint() {return "Hello Admin!";}
}
3. @Secured

基于角色的简单鉴权。

import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 只有ADMIN角色可以访问@GetMapping("/secured")@Secured("ROLE_ADMIN")public String securedEndpoint() {return "Secured Access!";}
}
4. @RolesAllowed

基于JSR-250标准的角色鉴权。

import javax.annotation.security.RolesAllowed;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {// 只有ADMIN角色可以访问@GetMapping("/rolesAllowed")@RolesAllowed("ADMIN")public String rolesAllowedEndpoint() {return "Roles Allowed Access!";}
}

4. 配置全局异常处理

当用户访问未授权的接口时,Spring Security会抛出AccessDeniedException。我们可以通过全局异常处理来返回友好的错误信息。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;@RestControllerAdvice
public class GlobalExceptionHandler {// 处理权限不足异常@ExceptionHandler(AccessDeniedException.class)public ResponseEntity<String> handleAccessDeniedException(AccessDeniedException e) {return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Access Denied: " + e.getMessage());}// 处理其他异常@ExceptionHandler(Exception.class)public ResponseEntity<String> handleException(Exception e) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error: " + e.getMessage());}
}

5. 测试接口鉴权

使用Postman或curl测试接口:

1. 登录获取Token
POST /authenticate
{"username": "admin","password": "password"
}
2. 访问受保护的接口
  • ADMIN接口:

    GET /api/admin
    Authorization: Bearer <token>
    
  • USER接口:

    GET /api/user
    Authorization: Bearer <token>
    
  • 未授权访问:
    如果用户没有权限,会返回403 Forbidden


6. 总结

通过以上步骤,我们实现了基于Spring Security的接口鉴权功能。主要步骤包括:

  1. 启用方法级安全注解。
  2. 定义用户角色和权限。
  3. 使用注解(如@PreAuthorize@Secured等)控制接口访问权限。
  4. 配置全局异常处理,返回友好的错误信息。

你可以根据实际需求扩展和调整这些配置,例如从数据库中动态加载权限、支持更复杂的权限表达式等。

相关文献

JWT(JSON Web Tokens) 详细介绍
【spring知识】Spring Security从入门到放弃

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

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

相关文章

Mac开启任何来源安装配置环境变量

目录 开启任何来源配置环境变量退出保存时如果没有权限修改文件权限拓展——.bash_profile和.zshrc 开启任何来源 sudo spctl --master-disable#打开软件时提示文件损坏 sudo xattr -r -d com.apple.quarantine 进入访达应用程序拖拽应用到终端配置环境变量 cd ~ vi ~/.bash…

使用 Logback 的最佳实践:`logback.xml` 与 `logback-spring.xml` 的区别与用法

在开发 Spring Boot 项目时&#xff0c;日志是调试和监控的重要工具。Spring Boot 默认支持 Logback 作为日志系统&#xff0c;并提供了 logback.xml 和 logback-spring.xml 两种配置方式。这篇文章将详细介绍这两者的区别、各自的优缺点以及最佳实践。 目录 一、什么是 Logbac…

excel实用工具

持续更新… 文章目录 1. 快捷键1.1 求和 2. 命令2.1 查找 vloopup 1. 快捷键 1.1 求和 windows: alt mac : command shift T 2. 命令 2.1 查找 vloopup vlookup 四个入参数 要查找的内容 &#xff08;A2 6xx1&#xff09;查找的备选集 &#xff08;C2:C19&#xff09;…

QModbusTCPClient占用内存持续增长

最近使用QModbusTCPClient通信&#xff0c;需要频繁发送读写请求&#xff0c;发现软件占用内存一直在增减&#xff0c;经过不断咨询和尝试&#xff0c;终于解决了。 1.方案一&#xff08;失败&#xff09; 最开始以为是访问太频繁&#xff0c;导致创建reply的对象比delete re…

adb 命令使用大全

1.adb针对设备 adb devices //查看链接设备 adb -s "设备序号" shell 命令 //选择设备执行 adb connect "ip地址" adb disconnect "ip地址" adb shell screencap -p /sdcard/screenshot.png //截图 adb pull /sdcard/filename …

Linux(Centos 7.6)命令详解:iconv

1.命令作用 将给定文件的编码从一种编码转换为另一种编码(Convert encoding of given files from one encoding to another) 2.命令语法 Usage: iconv [OPTION...] [FILE...] 3.参数详解 OPTION: 输入/输出格式规范: -f, --from-codeNAME&#xff0c;原始文本编码-t, --t…

读《SQL经典实例》学数据库(系列一)

目录 友情提醒第一章、数据库简述1.1&#xff09;数据库简述1.2&#xff09;常见的数据库软件1.3&#xff09;MySQL数据库安装 第二章、SQL语句分类2.1)操作数据仓库/数据表&#xff1a;DDL2.1.1&#xff09;创建数据仓库/数据表2.1.2&#xff09;删除数据仓库/数据表2.1.3&…

【C++】模板(进阶)

本篇我们来介绍更多关于C模板的知识。模板初阶移步至&#xff1a;【C】模板&#xff08;初阶&#xff09; 1.非类型模板参数 1.1 非类型模板参数介绍 模板参数可以是类型形参&#xff0c;也可以是非类型形参。类型形参就是我们目前接触到的一些模板参数。 //类型模板参数 …

算法项目实时推流

1、搭建流媒体服务器 下载mediamtx 2、视频流直推 ffmpeg -stream_loop -1 -i DJI_20250109112715_0002_W.MP4 -r 30 -c:v libx264 -preset ultrafast -f flv rtmp://192.168.100.20:1935/live/test_chengdu1 3、硬件加速 如果硬件支持&#xff0c;可以使用硬件加速编码器&am…

99.12 金融难点通俗解释:毛利率

目录 0. 承前1. 简述2. 比喻&#xff1a;冰淇淋店赚钱2.1 第一步&#xff1a;准备材料2.2 第二步&#xff1a;卖冰淇淋2.3 第三步&#xff1a;计算毛利率 3. 生活中的例子3.1 好的毛利率3.2 一般的毛利率3.3 差的毛利率 4. 小朋友要注意4.1 毛利率高不一定好4.2 毛利率低不一定…

一文学会YOLO系列算法(从V3到11)实现遥感图像目标检测

目录 前言 数据集介绍 数据集转换 YOLO代码的下载 YOLO的配置 1.数据集的配置 2.模型的配置 YOLO11模型的训练 其它版本YOLO的训练 前言 遥感技术的快速发展&#xff0c;特别是在高分辨率遥感图像的获取能力上的显著提升&#xff0c;已经大大拓宽了遥感数据在环境监测…

3.1 Go函数调用过程

在 Go 语言中&#xff0c;函数调用的核心机制依赖于内存的栈区分配和指针操作&#xff0c;理解这一原理有助于掌握函数的执行过程。 1. 内存结构概述 在 Go 程序编译成可执行文件并启动后&#xff0c;操作系统会为其分配进程内存&#xff0c;进程内存主要分为以下区域&#x…

图解Git——分布式Git《Pro Git》

分布式工作流程 Centralized Workflow&#xff08;集中式工作流&#xff09; 所有开发者都与同一个中央仓库同步代码&#xff0c;每个人通过拉取、提交来合作。如果两个开发者同时修改了相同的文件&#xff0c;后一个开发者必须在推送之前合并其他人的更改。 Integration-Mana…

案例分析一

张某&#xff08;10多年IT工作经验&#xff09;应聘一家国企单位&#xff0c;面试官&#xff08;技术副主管&#xff09;面试时问了些无关痛痒的问题&#xff0c;谈到薪资时强调我权限范围内的数额就那么多&#xff0c;再多就需要走申请流程进行操作了。 没几天入职后&#xf…

【高阶数据结构】布隆过滤器(BloomFilter)

1. 概念 1.1 背景引入 背景&#xff1a;在计算机软件中&#xff0c;一个常见的需求就是 在一个集合中查找一个元素是否存在 &#xff0c;比如&#xff1a;1. Word 等打字软件需要判断用户键入的单词是否在字典中存在 2. 浏览器等网络爬虫程序需要保存一个列表来记录已经遍历过…

【json_object】mysql中json_object函数过长,显示不全

问题&#xff1a;json只显示部分 解决&#xff1a; SET GLOBAL group_concat_max_len 1000000; -- 设置为1MB&#xff0c;根据需要调整如果当前在navicat上修改&#xff0c;只有效本次连接和后续会话&#xff0c;重新连接还是会恢复默认值1024 在my.ini配置文件中新增或者修…

计算机网络 (52)秘钥分配

一、重要性 在计算机网络中&#xff0c;密钥分配是密钥管理中的一个核心问题。由于密码算法通常是公开的&#xff0c;因此网络的安全性主要依赖于密钥的安全保护。密钥分配的目的是确保密钥在传输过程中不被窃取或篡改&#xff0c;同时确保只有合法的用户才能获得密钥。 二、方…

第35天:安全开发-JavaEE应用原生反序列化重写方法链条分析触发类类加载

时间轴&#xff1a; 序列化与反序列化图解&#xff1a; 演示案例&#xff1a; Java-原生使用-序列化&反序列化 Java-安全问题-重写方法&触发方法 Java-安全问题-可控其他类重写方法 Java-原生使用-序列化&反序列化 1.为什么进行序列化和反序列化&#xff1…

MindAgent:基于大型语言模型的多智能体协作基础设施

2023-09-18 &#xff0c;加州大学洛杉矶分校&#xff08;UCLA&#xff09;、微软研究院、斯坦福大学等机构共同创建的新型基础设施&#xff0c;目的在评估大型语言模型在游戏互动中的规划和协调能力。MindAgent通过CuisineWorld这一新的游戏场景和相关基准&#xff0c;调度多智…

Excel 技巧17 - 如何计算倒计时,并添加该倒计时的数据条(★)

本文讲如何计算倒计时&#xff0c;并添加该倒计时的数据条。 1&#xff0c;如何计算倒计时 这里也要用公式 D3 - TODAY() 显示为下面这个样子的 然后右键该单元格&#xff0c;选 设置单元格格式 然后点 常规 这样就能显示出还书倒计时的日数了。 下拉适用到其他单元格。 2&a…